Redis-集群

Redis的集群遵循的是CAP理论中的AP,因为Redis是出现网络分区的时候,主依然提供写服务,从会采用多中方式追赶主

主从复制和从从复制

Redis的主从复制、从从复制是异步复制,从从复制是为了减少主的压力

增量复制

Redis主会将涉及到数据修改的命令写入到Buffer中,然后异步传给从库,从库执行命令并且返回偏移量给主,保证俩边的数据一致,buffer采用环状结构,如果buffer满了会覆盖原来的数据。如果出现还没有执行就被覆盖的情况会触发快照复制

快照复制

快照复制很耗时。过程如下

  • 主先bgsave将快照写入到磁盘。
  • 同步快照给从
  • 从在接收完快照后,先持久化,在Load快照
  • 从库开始执行这段时间的增量操作。

    如果这段时间buffer又被覆盖了,则继续快照复制,如此恶性循环,所以要选择一个合适的复制buffer

    快照复制前会持久化,如果这时候正好需要aof的fsync,则会推迟fsync,影响主的业务。

    新加入的从库都需要先执行一遍快照复制。

    Redis3.0针对这种情况采用了无盘复制的思路,遍历内存不持久化,直接传递给从库,从库如上面的过程先持久化在load,避免了主库的磁盘IO操作

wait命令

可以将异步复制改为同步复制,由AP变为CP

redis-sentinel 哨兵机制

redis在3.0提供sentinel服务,进行节点的healthCheck。

客户端通过连接sentinel获取当前的master信息,客户端连接Master。

如果发现master挂了,哨兵会选举新的Master,同时集群中其他的slave会和新的master开始主从同步任务。当原来的master恢复会变为slave。

注意:实际上senintel的主从切换是客户端做的。

数据切片

Codis

codis-proxy:做请求代理
codis-server:服务存储

将数据分成1024个slot,数据写入时候proxy会对key做crc32求hash,然后根据槽取模。槽的映射关系会交给zookeeper和etcd这种第三方组件来维护。

槽的迁移,当发现请求的key正在迁移时候会强制key进行迁移之后在去新的槽去请求。

支持自动平衡。

缺点:因为不是官方的方案,所以支持新的特性比较困难,且不支持事物等命令。

Cluster

redis官方集群方案。

将数据分为16384个slot,每个节点都保留一份slot的配置信息,并且客户端链接时候会获取一份Slot信息,这部分信息持久化到redis-cluster中。

slot的跳转:当客户端发现请求的数据已经迁移后客户端会收到MOVED < newSlotNum > < ip:port >可以更新客户端的配置,然后去新的server去获取。

slot的迁移:迁移是以slot为单位进行迁移,当访问到迁移的key时候流程如下:

  • 想srcNodeAddr请求,如果key在srcNodeAddr进行操作
  • 如果不在srcNodeAddr,返回-ASKING tragetNodeAddr
  • 向tragetNodeAddr发送不带参数的ASKING节点
  • 返回OK,去tragetNodeAddr getKey (目的是ASKING之后告诉tragetNodeAddr下一条指令不能不处理,因为在迁移中理论上tartNode不负责这个key)

    redis的key如果是大Key,因为迁移指令是阻塞,会影响到服务。

    redis的集群管理是通过Gossip协议的。当一个节点发现另一个节点失联(PFail),它会广播给集群,然后当集群中其他节点收到的该节点失联事件过半数(PFail Count)时候,就标记该节点下线。

    另外,redis-cluster的槽位迁移、节点切换都是在客户端做的。

分布式锁的不安全性

由于主节点宕机客户端无感知,所以当客户端从主节点获取锁后,未同步到从节点这时候发生宕机。锁数据未同步成功发生了主从切换,锁是失效的,如果业务不容忍可以采用redlock机制。