当前位置:   article > 正文

Redis分布式解决方案 codis

Redis分布式解决方案 codis

引言

在大数据高并发场景下,单个Redis实例往往会显得捉襟见肘。首先体现在内存上,单个Redis的内存不宜过大,内存太大会导致rdb文件过大,进一步导致主从同步时全量同步时间过长,在实例重启恢复时也会消耗很长的时间加载数据。其次,体现在CPU利用率上,单个Redis实例只能利用单个核心,单个核心要完成海量数据的存取和管理工作压力会很大。

正是在这样的大数据高并发需求之下,Redis集群方案应运而生。他可以将多个众多小内存的Redis实例综合起来,将分布在多台机器上的众多CPU核心的计算能力聚集到一起,完成海量数据存储和高并发读写操作。
在这里插入图片描述

Codis上挂接的 所有Redis实例构成一个Redis集群,当集群空间不足时,可以通过动态增加Redis实例来实现扩容需求。

客户端操作Codis同操作Redis几乎没有区别,还是可以使用相同的客户端SDK,不需要任何变化。

因为Codis是无状态的,他只是一个转发代理中间件,意味着我们可以启动多个Codis实例,供客户端使用,每个Codis节点都是对等的。因为单个Codis代理能支撑的QPS比较有限,通过启动多个Codis代理可以显著增加整体的QPS需求,还能起到容灾功能。
在这里插入图片描述

分片原理

Codis要负责将特定的key转发到特定的Redis实例,Codis将所有的key默认划分为1024个槽位(slot),他首先将客户端传来的key进行crc32运算计算哈希值,再将hash后的整数值对1024这个整数进行取模得到一个余数,这个余数就是对应key的槽位,每个槽位都会唯一映射到后面的多个Redis实例之一,Codis会在内存维护槽位和Redis实例的映射关系。

在这里插入图片描述

不同的Codis实例之间槽位关系如何同步

如果Codis的槽位映射关系只存储在内存里,那么不同的Codis实例之间的槽位关系就无法得到同步。所以,Codis需要一个分布式配置存储数据库专门用来持久化槽位关系。
在这里插入图片描述
Codis将槽位关系存储在zk中,并且提供了一个Dashboard可以用来观察和修改槽位关系,当槽位关系变化时,Codis Proxy会监听到变化并重新同步槽位关系。从而实现多个Codis Proxy之间共享相同的槽位关系配置。

扩容

刚开始Codis后端只有一个Redis实例,1024个槽位全部指向同一个Redis。然后一个Redis实例内存不够了,所以又加了一个Redis实例,这时候需要对槽位关系进行调整,将一半的槽位划分到新的节点。这意味着需要对这一半的槽位对应的所有key进行迁移,迁移到新的Redis实例。

Codis对Redis进行了改造,增加了slotsscan指令,可以遍历指定slot下所有的key。然后迁移每个key到新的Redis节点。

在迁移过程中,Codis还是会接收到新的请求落在当前正在迁移的槽位上,因为当前槽位的数据同时存在于新旧两个槽位中,Codis无法判定迁移过程中的key究竟在哪个实例中,所以采用了另一种完全不同的思路。当 Codis接收到位于正在迁移槽位中的key后,会立即强制对当前的单个key进行迁移,迁移完成后,再将请求转发到新的Redis实例

在这里插入图片描述

Codis的代价

Codis给Redis带来了扩容的同时,也损失了一些其他特性。因为Codis中所有的key分散在不同的Redis实例中,所以事务就不再支持。事务只能在单个Redis实例中完成。

同时,为了支持扩容,单个key对应的value不宜过大,因为集群的最小迁移单位是key。对于一个hash结构,他会一次性使用hgetall拉取所有内容,然后使用hmset放置到另一个节点。如果hash内部的kv太多,容易带来迁移卡顿。

Codis因为增加了Proxy作为中转层,所以在网络开销上要比Redis 大,整体性能上比单个Redis性能有所下降。

Codis集群配置中心使用zk来实现,在部署上增加了zk运维的代价。

Mget指令的操作过程

在这里插入图片描述
mget指令用于批量获取多个key的值,这些key 可能会分布在多个Redis实例中。Codis的策略是将key按照所分配的实例打散分组,然后依次对每个实例调用mget方法,最后将结果进行汇总,返回给客户端。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/812619
推荐阅读
相关标签
  

闽ICP备14008679号