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方法,最后将结果进行汇总,返回给客户端。

相关推荐

  1. Redis可以用作分布式共享session的解决方案

    2024-07-09 17:58:03       37 阅读
  2. 分布式解决方案

    2024-07-09 17:58:03       39 阅读
  3. redis穿透解决方案

    2024-07-09 17:58:03       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-09 17:58:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-09 17:58:03       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-09 17:58:03       58 阅读
  4. Python语言-面向对象

    2024-07-09 17:58:03       69 阅读

热门阅读

  1. 57、Flink 的项目配置概述

    2024-07-09 17:58:03       30 阅读
  2. git杂记

    git杂记

    2024-07-09 17:58:03      27 阅读
  3. [Python学习篇] Python面向对象——继承

    2024-07-09 17:58:03       29 阅读
  4. 【Linux命令入门】查找文件

    2024-07-09 17:58:03       23 阅读
  5. 编码与梦想:我的CSDN创作5周年

    2024-07-09 17:58:03       24 阅读
  6. 多数据库支持在PHP框架中的实现策略与实践

    2024-07-09 17:58:03       30 阅读
  7. JVM 堆内存分配过程

    2024-07-09 17:58:03       29 阅读
  8. c++单例模式的一种写法

    2024-07-09 17:58:03       25 阅读
  9. nunjucks动态更新模版路径

    2024-07-09 17:58:03       24 阅读
  10. 【python技巧】pytorch网络可视化

    2024-07-09 17:58:03       28 阅读