点赞再看,养成习惯,微信搜索「 小大白日志」关注这个搬砖人。
文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。
数据结构 应用场景 string 普通的键值对存储 list(元素可重复) 粉丝列表、文章评论 set(元素不重复) 获取交集、并集的用户数据 zset(元素不重复) 获取排名靠前的用户 hash 存储用户属性后支持快速修改
数据结构 应用场景 hyperLogLog 基数统计,如统计一个网站首页一天的用户访问量(一个用户每天访问多次只能算一次访问) geo 摇一摇、查看附近的人 Pub/Sub发布订阅 订阅频道
redis4.0以上提供了module,用户可以根据自己的需求扩展redis的功能,比如布隆过滤器
如果大量的key在同一个时间点过期,则在这个时间点redis可能会出现卡顿,严重的话缓存雪崩,在给key设置失效时间后,可以再添加一个随机失效时间使所有key的失效时间不集中在某个时间点(电商页面需要使用定时任务定时刷新redsi缓存)
- aof和rdb都是把缓存中的数据存入磁盘,分别形成.aof和.rdb文件
- rdb是间隔一定时间就把redsi缓存里面的数据以镜像的方式存入磁盘,在下一次持久化之前如果发生故障则会丢失最新的缓存数据,比较适合对数据完整性要求不严格的情况;rdb方式会使用一个fork子进程持久化数据,而主进程则保持处理正常命令,所以主进程不会进行I/O操作
- aof有always/everysec/no三种方式实时地将redis命令持久化到磁盘中(每次都在文件内容后面增加新内容),所有aof文件肯定比rdb文件大,恢复数据时rdb比aof的快
-
建议优先使用aof持久化,最好同时开启两种持久化方式,如果同时开启则redis默认优先使用aof方式持久化
-
使用一致性哈希算法:在分布式缓存环境中,简单的哈希算法将key被保存在【key.hashcode()%N】中,N=服务器数=redis节点数,但是扩容增加服务器时原有节点的映射关系就变了;而一致性哈希算法是将【0~ 2^(31-1)】 个位置看做一个环,所有key和所有节点都对将 2^(31-1) 进行求余从而确定其在 2^(31-1)哪个位置,即【key.hashcode()% 2^(31-1)】、节点可以用IP或其他因子如【节点IP% 2^(31-1) 】,确定key在2^(31-1)这个环空间的位置后,顺时针方向找”最近的节点所在环中的位置”,该节点便是这个key的存储位置;
- 一致性哈希算法产生的问题:如果redis集群中节点太少,就会导致节点分布在环中的位置不均匀,从而导致key不均匀地分布在redis节点缓存中,进而导致某些节点数据压力过大,解决:在节点数量少的时候,可以给每个节点=真实节点设置同等数量的’虚拟节点’,这些虚拟节点也对 2^(31-1)求余,当某个key落在虚拟节点的时候实际上是落在它的真实节点上,如下图,问题解决!
* 一致性哈希算法的思想如何在redis集群中使用:redis没有使用一致性哈希算法,而是引入了它的概念=>在redis集群中设置16384个槽(相当于这个环有16384个位置),这16384个槽均匀地分布在N台服务器上(即N个redis节点,每个节点所处的环位置就是该节点’最大的槽号’),key会被保存在第【key.hashcode()%16384】=【CRC16(key)%16384】号槽中,离该key槽号有另外一个槽号=某个节点A的最大槽号,则该key就存放在这个A节点中;当需要增加1个redis节点扩容时,把原所有节点的一部分槽分给新节点即可;当需要减少1个节点缩容时,把那个节点的槽移到其他节点即可
- 定时删除:给每个key设置一个定时器,到点就删除对应的key-value,缺点是定时器会消耗大量的CPU资源
- 惰性删除:使用到这个key的时候去检查是否过期,若过期就删除,缺点是只有在用到的时候才会去检查删除内存中的数据,若没用到且过期的数据则一直占据着内存比较耗费内存
- 定期删除:设置一定的时间周期,选择性地扫描redis内存中的expire字典(内含ekey-evalue,expire的ekey是指向redis中key的指针,evalue是该key的过期时间),过期则删除,注意是扫描部分key而非全部扫描
redis默认使用后两种删除策略
redis的过期淘汰策略是指定key-value过期时怎么处理,而redis的内存淘汰策略是指在插入新key-value时,剩余空间不足则如何处理,处理措施分两种情况:
- 对于所有设置了过期时间的key:
- 删除最近最少使用的key(LRU算法,常用)
- 随机删除某个key
- 删除存在时间最长的那个key
- 对于所有的key-value,不管有没有设置过期时间:
- 报错
- 删除最近最少使用的key(LRU算法,常用)
- 随机删除某个key
利用好五种常用的数据结构类型;复杂的存储尽量用hash结构,因为hash占空间少
redis事务中可含多条命令,每条命令都是原子性的、按顺序执行的;每个事务互不影响相互隔离;事务中某条命令执行失败,其他命令仍可以执行成功(故事务不保证原子性:要么全部执行成功要么全部失败),且redis事务不提供回滚功能
主要有三种:主从模式、哨兵sentinel模式、redis-cluster模式
- 哨兵模式
- sentinel可以发消息通知:当redis集群中某个节点下线了,发消息给管理员
- sentinel可以对redis主节点”故障转移”:sentinal进程会监听主从节点是否正常工作,当大部分sentinel节点都认为主节点挂掉时,会在从节点中重新选举主节点:sentinal集群可能会有多个sentinal,但这些sentinal的信息会被保存为一份相同的列表,列表再被各个sentinal各自保存,重新选举时,列表中排第一位的sentinal开始对主节点执行”故障转移”(转移原主节点的数据到新主节点),执行失败再由第二位sentinal执行。当从节点被选为新的主节点后,此时”故障转移”已经算是成功了,然后sentinal会把旧主节点的信息写进新主节点,然后再广播新主节点的信息
- sentinel集群+redis集群保证高可用:至少是3个sentinel节点才能组成sentinel集群,且sentinel集群+redis集群只保证高可用行,不保证数据是否丢失
- redis cluster模式
- redis的cluster模型:允许将数据按照约定的规则分开存储在多个redis服务器机器上,避免redis单机存储容量过小
- redis集群会有16384个散列槽,当增加集群中的redis节点时,只需将部分散列槽移动到新redis节点当减少redis节点时,把散列槽移到其他节点即可往redis集群中添加(key,value)时,由算法=【CRC16(key)%16384】决定将key放到哪个散列槽取出key时也用同样的算法取出;
- redis集群中保存key-value时可能会发送到任一redis节点,该节点会将key-value发到正确的节点上;读取key时,若key不在本节点上,则本节点执行转向命令转向正确的节点
将所有key-value分布在不同的节点上,这样能充分利用多台计算机的内存和CPU处理能力;
缺点:
- 存在于不同节点的key不能做set交集等操作;
- 需要同时处理每个节点的aof/rdb文件
分区的两种方式:
- 客户端分区,在用户的客户端就已经决定好把key保存到哪个节点上
- 查询路由分区,把key请求发到任一节点上,再由该节点决定转发到哪个最终节点保存
红锁=redis官方提供的一种实现分布式锁的算法,它保证分布式环境下只有一个客户端能拿到某共享资源的锁,且永远不会因为宕机或其他原因等造成死锁
当某个节点发生故障从而影响到核心功能服务,仍要提供正常服务给用户,即使提供的是有损的服务。常见的如某个redis出现故障,为防止大量请求去到数据库而导致雪崩,可以直接返回默认值。
- redis支持复杂的数据结构(常见有5种数据类型),而memcached保存的所有值都是简单的string
- redis支持持久化到硬盘,而memcached数据只能存在于内存中,故每次启动应用需要重新按需加载数据到memcached中
- 处理小数据量时redis快,大数据量时memcached快
有些数据需要同时写入数据库和写入缓存,应尽量保证数据库和缓存的双写一致性:如果先写redis缓存,若redis写成功而数据库失败则出现脏读->必须先写数据库再写redis缓存,若数据库写成功而redis写入失败,则在下次读取缓存值的时候,先读数据库再加载到缓存中。
OK,如果文章哪里有错误或不足,欢迎各位留言。
创作不易,各位的「 三连」是二少创作的最大动力!我们下期见!
Original: https://www.cnblogs.com/mofes/p/15101148.html
Author: 明天喝可乐
Title: redis篇
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/589753/
转载文章受原作者版权保护。转载请注明原作者出处!