Redis Cluster
直接集成了replication(同步)和sentinal(哨兵)的功能
是Redis的集群模式
- 自动将数据进行分片,每个master上放一部分数据
- 提供内置的高可用支持,部分master不可用时,还是可以继续工作的
在redis cluster架构下,每个redis要放开两个端口号,比如一个是6379,另外一个就是加10000的端口号,比如16379端口号是用来进行节点间通信的,也就是cluster bus的东西,集群总线。cluster bus的通信,用来进行故障检测,配置更新,故障转移授权
Redis Cluster有固定的16384个Hash slot,对每个key计算CRC16值,然后对16384取模,可以获取key对应的hash slot,redis cluster中每个master都会持有部分slot,比如有3个master,那么可能每个master持有5000多个hash slot,hash slot让node的增加和移除很简单,增加一个master,就将其他master的hash slot移动部分过去,减少一个master,就将它的hash slot移动到其他master上去,移动hash slot的成本是非常低的,客户端的api,可以对指定的数据,让他们走同一个hash slot,通过hash tag来实现
如果有一台master宕机了,其它节点上的缓存几乎不受影响,因为它取模运算是根据 Hash slot来的,也就是 16384,而不是根据Redis的机器数
Redis实现高并发:
一主多从,一般来说,很多项目其实就足够了,单主用来写数据,单机几万QPS,多从用来查询数据,多个从实例可以提供每秒10万QPS 其中主节点以写为主(可写也可以读),从节点只能读不可写入!
Redis高并发的同时,还需要容纳大量的数据:一主多从,每个实例都容纳了完整的数据,比如Redis主就10G内存量,其实你就可以对只能容纳10G的数据量。如果你的缓存要容纳的数据量很大,达到了几十G,甚至几百G,那就需要使用到Redis集群,而且用Redis集群之后,提供可能每秒几十万的读写并发。
Redis高可用:如果用主从架构部署,在加上哨兵就可以实现任何一个实例宕机,就会自动进行主备切换。
Redis 集群中的主从复制
为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。
在之前列举的节点 A 、B 、C 的例子中, 如果节点 B 下线了, 那么集群将无法正常运行, 因为集群找不到节点来处理 5501 号至 11000 号的哈希槽。
另一方面, 假如在创建集群的时候(或者至少在节点 B 下线之前), 我们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理 5501 号至 11000 号的哈希槽, 这样集群就不会因为主节点 B 的下线而无法正常运作了。
不过如果节点 B 和 B1 都下线的话, Redis 集群还是会停止运作。
复制模式
- 全量复制:master 全部同步到 slave
-
问题点
同步故障
- 复制数据延迟(不一致)
- 读取过期数据(Slave 不能删除数据)
- 从节点故障
- 主节点故障
- 配置不一致
- maxmemory 不一致:丢失数据
- 优化参数不一致:内存不一致.
- 避免全量复制
- 选择小主节点(分片)、低峰期间操作.
- 如果节点运行 id 不匹配(如主节点重启、运行 id 发送变化),此时要执行全量复制,应该配合哨兵和集群解决.
- 主从复制挤压缓冲区不足产生的问题(网络中断,部分复制无法满足),可增大复制缓冲区( rel_backlog_size 参数).
- 复制风暴
缓存失效策略
一般而言,缓存系统中都会对缓存的对象设置一个超时时间,避免浪费相对比较稀缺的缓存资源。对于缓存时间的处理有两种,分别是主动失效和被动失效。
主动失效
主动失效是指系统有一个主动检查缓存是否失效的机制,比如通过定时任务或者单独的线程不断的去检查缓存队列中的对象是否失效,如果失效就把他们清除掉,避免浪费。主动失效的好处是能够避免内存的浪费,但是会占用额外的CPU时间。
被动失效
被动失效是通过访问缓存对象的时候才去检查缓存对象是否失效,这样的好处是系统占用的CPU时间更少,但是风险是长期不被访问的缓存对象不会被系统清除。
缓存淘汰策略
缓存淘汰,又称为缓存逐出(cache replacement algorithms或者cache replacement policies),是指在存储空间不足的情况下,缓存系统主动释放一些缓存对象获取更多的存储空间。
对于大部分内存型的分布式缓存(非持久化),淘汰策略优先于失效策略,一旦空间不足,缓存对象即使没有过期也会被释放。这里只是简单介绍一下,相关的资料都很多,一般LRU用的比较多,可以重点了解一下。
FIFO
先进先出(First In First Out)是一种简单的淘汰策略,缓存对象以队列的形式存在,如果空间不足,就释放队列头部的(先缓存)对象。一般用链表实现。
LRU
最近最久未使用(Least Recently Used),这种策略是根据访问的时间先后来进行淘汰的,如果空间不足,会释放最久没有访问的对象(上次访问时间最早的对象)。比较常见的是通过优先队列来实现。
LFU
最近最少使用(Least Frequently Used),这种策略根据最近访问的频率来进行淘汰,如果空间不足,会释放最近访问频率最低的对象。这个算法也是用优先队列实现的比较常见。
分布式缓存的常见问题
缓存穿透
DB中不存在数据,每次都穿过缓存查DB,造成DB的压力。一般是网络攻击
解决方案:放入一个特殊对象(比如特定的无效对象,当然比较好的方式是使用包装对象)
缓存击穿
在缓存失效的瞬间大量请求,造成DB的压力瞬间增大
解决方案:更新缓存时使用分布式锁锁住服务,防止请求穿透直达DB
缓存雪崩
大量缓存设置了相同的失效时间,同一时间失效,造成服务瞬间性能急剧下降
解决方案:缓存时间使用基本时间加上随机时间
