redis的集群方式主要有以下三种:
1、 主从模式
master挂掉之后,slave仍能正常读,但redis不再提供写服务,直到master重新启动
slave挂掉之后不影响其他slave的读和master的读写,slave重启后重新同步master数据
主写从读:
主库写,从库读,从库挂掉之后从主库读。
主读写从备份:
主库读写,从库只做备份。主库挂掉之后,redis不再工作
主从一致:
从库启动后,主动向master发送SYNC命令,master将保存快照(RDB持久化数据)和 保存快照到当前时间的缓存命令 发送给slave。slave接收消息后加载快照和执行缓存命令
slave上线后,master每次接收写命令都会发给slave,保证主从一致。
缺点:
master挂掉之后不能再提供写服务。单点故障
优点:
简单,易维护。省资源
2、哨兵模式
监控redis集群的状态,在master挂掉之后,重新选择新的master。选择机制:
- 使用如下条件筛选备选node:
- slave节点状态处于S_DOWN,O_DOWN,DISCONNECTED的除外
- 最近一次ping应答时间不超过5倍ping的间隔(假如ping的间隔为1秒,则最近一次应答延迟不应超过5秒,redis sentinel默认为1秒)
- info_refresh应答不超过3倍info_refresh的间隔(原理同2,redis sentinel默认为10秒)
- slave节点与master节点失去联系的时间不能超过( (now - master->s_down_since_time) + (master->down_after_period * 10))。总体意思是说,slave节点与master同步太不及时的(比如新启动的节点),不应该参与被选举。
- Slave priority不等于0(这个是在配置文件中指定,默认配置为100)。
- 从备选node中,按照如下顺序选择新的master
- 较低的slave_priority(这个是在配置文件中指定,默认配置为100)
- 较大的replication offset(每个slave在与master同步后offset自动增加)
- 较小的runid(每个redis实例,都会有一个runid,通常是一个40位的随机字符串,在redis启动时设置,重复概率非常小)
- 如果以上条件都不足以区别出唯一的节点,则会看哪个slave节点处理之前master发送的command多,就选谁。
哨兵也是有集群的,哨兵之前也是互相监控的,哨兵和redis集群之前是多对多的关系。
哨兵监控master流程:
- 哨兵每秒向master、slave发送一次ping命令,每10s发送一次info命令。
- 如果实例回复的时间比设置的时间要晚,则实例会被标记为主观下线
- 如果master被标记为主观下线,则监控该master的所有哨兵会向该master每秒发送一次ping,确认其下线。
- 当有足够多的哨兵确认了该master的下线状态,则该master就会被标记为客观下线。
- 如果master被标记为客观下线,则哨兵向所有slave发送INFO命令每s一次。
- 若没有足够多的哨兵同意master下线则master客观下线状态会被解除。若master重新向哨兵相应,则master主观下线状态解除。
3、集群模式
可以说是哨兵模式和主从模式的结合。cluster模式有多个节点,每个节点都有主从。主要解决单机redis内存不够的问题。
redis集群通过哈希槽将redis数据分布式存储到集群的master节点中,slave节点不工作,仅在master节点挂掉之后替换master继续提供服务。
redis每个节点负责一部分哈希槽位。
集群节点的扩展/收缩方式:
- 首先启动一个 Redis 节点,记为 M4。
- 使用 cluster meet 命令,让新 Redis 节点加入到集群中。新节点刚开始都是主节点状态,由于没有负责的>槽,所以不能接受任何读写操作,后续我们就给他迁移槽和填充数据。
- 对 M4 节点发送 cluster setslot { slot } importing { sourceNodeId } 命令,让目标节点准备导入槽的数据。 >4) 对源节点,也就是 M1,M2,M3 节点发送 cluster setslot { slot } migrating { targetNodeId } 命令,让源节>点准备迁出槽的数据。
- 源节点执行 cluster getkeysinslot { slot } { count } 命令,获取 count 个属于槽 { slot } 的键,然后执行步骤>六的操作进行迁移键值数据。
- 在源节点上执行 migrate { targetNodeIp} " " 0 { timeout } keys { key... } 命令,把获取的键通过 pipeline 机制>批量迁移到目标节点,批量迁移版本的 migrate 命令在 Redis 3.0.6 以上版本提供。
- 重复执行步骤 5 和步骤 6 直到槽下所有的键值数据迁移到目标节点。
- 向集群内所有主节点发送 cluster setslot { slot } node { targetNodeId } 命令,通知槽分配给目标节点。为了>保证槽节点映射变更及时传播,需要遍历发送给所有主节点更新被迁移的槽执行新节点。
客户端路由:
- smart集群客户端维护了一张哈希槽对应节点的关系列表。
- 客户端根据本地 slot 缓存发送命令到源节点,如果存在键对应则直接执行并返回结果给客户端。
- 如果节点返回 MOVED 错误,更新本地的 slot 到 Redis 节点的映射关系,然后重新发起请求。
- 如果数据正在迁移中,节点会回复 ASK 重定向异常。格式如下: ( error ) ASK { slot } { targetIP } : { targetPort }