Redis集群分片存储与一致性hash问题

Redis集群分片存储与一致性hash问题

Redis官方集群方案

问题:假设场景,需要将3000w用户数据存储至Redis中,内存需求10GB,单机压力庞大,如何存储?

火车问题转换,每一节车厢可以坐很多人,根据车票找到对应的座位,火车根据不同座位号,划分车厢。

类比Redis cluster,每一个Redis实例都是一个车厢,存储的数据需要一个座位,引入一种虚拟槽slot概念,每个Redis内部对应一部分槽位slot(类似于车厢座位)

Redis集群分片存储与一致性hash问题


模拟数据存储过程

Redis服务端通过hash计算位置,crc16 hash key计算得到槽位,即得到数据存储的Redis服务。

假设存在数据(key :hello)需要存储,先把key计算hash值 ,哈希值 % 16384 取模,便是该条数据在Redis集群中存储的slot槽位号。

Redis集群分片存储与一致性hash问题

客户端发送数据时,会先请求一台Redis服务器,假设该Redis服务存储的slot槽位号与数据存储的slot不一致,则会返回一条重定向数据,说明数据应该存储在另一台Redis服务上。

客户端会缓存slot分配信息,发送命令前,客户端进行slot计算,根据slot分配信息,定位到Redis-Server。缓存slot信息提高存储性能。


扩容与减少服务

  • Redis扩容,启动新Redis服务并且添加进入集群后,只需要将部分槽位号分配给新的Redis服务。
  • Redis减少服务,需要把数据清空或者分配给其他主节点。

Redis集群问题

cluster集群不保证数据一致,数据也可能丢失

正常情况下,客户端写入或读取数据,当一个节点故障,主节点关闭,在主从切换的过程中,这个时间段的操作,对于客户端的来说,只能是失败。导致数据丢失。


Redis集群大小 16384个槽
  • 理论上最多可以16384个Redis实例组成集群
  • 节点之间交换信息,传递信息包括槽的信息,带来带宽消耗 官方建议1000个以内
  • 一致性hash算法

集群 ask和moved重定向
  • moved,确定数据slot不属于当前节点,Redis会返回moved
  • ask,若当前Redis节点正处于slot迁移(reshard)过程,则代表此处请求对应的key暂时不在此节点,返回ask,告诉客户端本次请求重定向

数据倾斜与访问倾斜问题
  • 前期业务层面提前预防,热点key在设计中规避
  • 后期slot迁移,压力分摊

读写分离在集群模式中不可用
  • 集群中的主从方案主要用于高可用,并非用于读写分离。默认所有从节点上的读写,都会重定向到key对应的槽位主节点上。
  • 可在读取过程中,设置readonly,当前连接只读模式,需要写数据时再设置readwrite模式取消当前可读。

一致性哈希

普通哈希算法

普通hash算法是将key取得hash值后,与节点的数量取模,得到位置。如果增加节点或者删除节点,所有数据的hash值取模都会改变,所有的数据都失效。

一致性哈希算法

一致性哈希是一个环形hash空间,按照hash算法将对应的key哈希到一个具有2^32-1个桶的空间中。

每个节点负责一部分桶,例如节点R1负责hash 0 - 10000 的桶。这种设计可以弹性的增加节点或删除节点。

Redis集群分片存储与一致性hash问题