Codis就是一个Redis代理中间件,其对外协议与Redis协议保持一致,当客户端向Codis发送指令时,Codis负责将指令转发到后面的Redis实例来执行并将返回结果再转回给客户端。
Codis挂接的所有Redis实例构成一个Redis集群,当集群空间不足时,可以通过动态增加Redis实例来实现扩容需求。
问题1:Codis是如何分发客户端请求的呢???
答:
第一步:Codis将所有的key默认划分为1024个槽位(slot),它首先对客户端传过来的key进行crc32运算计算哈希值,再将 hash后的整数值对1024这个整数进行取模得到一个余数,这个余数就是对应key的槽位。(槽位数量默认是1024,它是可以配置的)
第二步:每个槽位都会唯一映射到后面的唯一一个Redis实例。
问题2:由于Codis也可以组成集群,那如何把集群中某个Coids槽位与key映射关系同步到其他Codis中呢?
答:这里Codis必须使用一个分布式数据库来实现这个目标,比如:ZooKeeper、etcd等。
问题3:还有个问题就是,假如1024个槽位映射到N个Redis实例,假如现在变成了(N+M)个Redis实例,那1024个槽位映射关系该怎么重写?
答:通过Codis的SLOTSSCAN指令来扫描1024个槽位所对应的key,然后筛选出符合条件的key,最后把这些key映射到新增加的Redis实例。
同时在新映射这个过程中,某些客户端请求恰恰落在这些待迁移的槽位上,由于当前槽位的数据同时存在于新旧两个槽位中,Codis无法判定迁移过程中的key究竟在哪个实例中,所以当Codis接收到位于正在迁移槽位中的key后,会立即强制对当前的单个key进行迁移,迁移完成后,再将请求转发到新的Redis实例。
同时Redis新增实例,手工均衡太繁琐,Codis提供了自动均衡功能。自动均衡会在系统比较空闲的时候观察每个Redis实例对应的 Slots数量,如果不平衡,就会自动进行迁移。
问题4:那Codis的缺点是什么?
答:
①不同key映射到不同的Redis实例,因此无法跨实例来支持事务。
②rename指令变得很危险,如果rename前后名字被映射到不同的Redis实例下,那rename指令无法被正确执行。
③key的数量不能太多,因为我需要取哈希,再去1024取余,如果key数量太多,会给迁移带来卡顿。官方建议单个集合结构的总字节容量不要超过1M。
④Codis作为中间件,直面客户端请求,因此网络开销比单个Redis大。
⑤如果Codis作为集群使用,必须使用分布式数据库,例如:ZooKeeper,而为了维护ZooKeeper也是一定工作量。
⑥Codis作为非官方Redis集群方案,当官方Redis有变化的时候它要实时去跟进。
来源:CSDN
作者:弱即罪
链接:https://blog.csdn.net/attack_breast/article/details/103845114