集群篇
这一篇内容书上讲的有点水很细节的东西没有讲到,只是原理,细节的东西再在别的地方再找找。
主从同步
实现了读写分离,主写从读,优化点在大量的读操作被从均摊。
通常情况下主服务支持读写,从服务数据由主服务同步来,对外为只读,构成一主多从结构。可以在启动前配置文件中修改,也可以启动后使用slaveof命令修改。
主从同步的方式分为了两种:
- 增量同步
- 主节点:一边处理指令,一边异步将指令同步给从节点
- 从节点:一边处理主节点的指令来达到一致的状态,一边反馈给主节点自己同步到了哪里。
主节点会维护一块大小有限的内存,用来buffer最近的指令。并且会为每一个从节点记录一个索引值,表示该从节点在buffer中的指令同步到了哪里。如果网络状况不好,会导致从节点没有同步的指令多余buffer,这样的话从节点就需要进行一次快照同步。如果buffer过小,会导致无限快照同步。
- 快照同步
- 主节点:首先生成全量rdb数据,然后将其同步给从节点。
- 从节点:清空内存并加载同步来的rdb数据,完成后再接着继续进行增量同步。
这种同步方式对于主节点的负载影响较大,由于生成rdb是磁盘io操作还会影响aof的fsync,因此在2.8支持无盘复制,将rdb内容直接通过网络传输给从节点,而不再写入磁盘。
- wait指令
在写一条数据后使用wait指令可以使异步的主从同步变成同步的。“wait {num} {time}” 接受两个参数,第一个是要等待完全同步的从节点的数量,第二个是等待的超时时间,若为零则无限等待。
慎用,wait会阻塞主节点的服务直到超时或同步完成,可能会出现无限阻塞的问题。
哨兵模式 sentinel
通过sentinel管理主从结构,实现了自动故障迁移,提升了整体的容错率
在sentinel启动时只需要配置好要监控的主服务器即可,它会在启动后,根据监控的主服务配置获得从服务的信息从而监控刀整个主从结构。而且一个sentinel可以配置多个主服务,同时监控多个集群。而sentinel作为一个管理者,只有一个节点也不安全,因此要有至少三个节点形成sentinel网络。
sentinel内由多个定时任务来实现:
- 定期获取主从结构信息
- 定期获取所有节点的生存状态
- sentinel节点间定期交换各自信息
切换过程:
- 当某一个节点联系不上master时,会将其标记为主观下线,而此时并没有真实下线
- 当超过半数(可配置)的节点都认为master主观下线时,master被标记为客观下线,并启动切换
- 所有的节点中投票推举出一位领头节点来操作切换,领头节点会选出升级为新master的节点,然后将最新配置广播同步给其他的节点
- 等不可用的旧master恢复后,由领头节点将其设置为新的slave,然后切换过程结束。
只有master不可用时才会有上面的过程,slave下线的话不会有额外操作,因为在定时的状态监测中会发现该slave已经为不可用的状态。
sentinel网络的建立是在所监控的master上建立的pub/sub频道进行信息交换时候发现对方的,他们之间后续的信息交换也是在这里进行的,而对于sentinel下线的问题并没有处理,因此sentinel节点下线需要对所有sentinel节点reset。
通常配置:
一般配置为一主两从三哨兵,尽量使三个redis实例分布在不同的机器上且每个机器一个哨兵。
**参考:**更详细的理论讲解与实际使用,在这里有两篇很长的文章,是很好的教程。1 2
twemproxy
这是一个由twitter开源的redis集群模式,还支持memcache。原理就是增加了一层代理节点,代理节点通过散列函数将key散列到所有的redis节点上。客户端来的请求由代理转到相应的节点处理。对于多个redis节点加一个twemproxy节点的结构来说,在客户端看来性能与单台redis差不多,因此对于性能的提升需要多个代理节点均摊压力才行。
优点是简单轻量,缺点是添加redis节点要重新启动,而且数据不能rebalance,需要手动操作。
codis
这个是书上介绍的另一种集群模式,通过对key进行分slot,找到承包该slot的redis处理,从而管理redis集群。而且支持人工分配修改slot的分配,所以集群中心由zookeeper管理slot的分配关系。
他有个优势是在空闲时候会定期查看每个slot的状态,并进行迁移保持平衡。因为slot的分配会变化,
优点是在添加redis节点时,会自动均衡redis实例中slot的不平衡关系,进行数据迁移。而且有直观的前端页面来查看管理集群。
redis cluster
redis3.0提出的官方的集群化方案,是一个去中心化的集群,集群内部使用了raft和gossip实现一致性。
集群的全部redis节点都独立启动之后,可以使用redis-trib来建立管理redis cluster集群。集群内部也是由slot的方式来分配key,也可以在启动的时候使用工具手动分配一些slot的关系。这样一来,对于任意的key,所有的节点都知道的分配到哪个实例,所以客户端在连接的时候连接任意一个节点都可以,然后进行操作时,如果操作的key不由该节点负责,则会被重定位到负责该key的节点。
在集群运行时,也有sentinel模式的自动主从切换功能,一旦某个主节点不可用就会提升其从节点为主节点。如果没有可以提升的,导致某些slot不可用,redis集群则进入关闭状态,等到其中一个恢复正常工作并且全slot可用才恢复正常。