redis 集群 2:分而治之 —— Codis

news2024/12/23 18:14:40

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

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

img
img

Codis 是 Redis 集群方案之一,令我们感到骄傲的是,它是中国人开发并开源的,来自前豌豆荚中间件团队。绝大多数国内的开源项目都不怎么靠谱,但是 Codis 非常靠谱。有了 Codis 技术积累之后,项目「突头人」刘奇又开发出来中国人自己的开源分布式数据库 —— TiDB,可以说 6 到飞起。👍

从 Redis 的广泛流行到 RedisCluster 的广泛使用之间相隔了好多年,Codis 就是在这样的市场空缺的机遇下发展出来的。大型公司有明确的 Redis 在线扩容需求,但是市面上没有特别好的中间件可以做到这一点。

img
img

Codis 使用 Go 语言开发,它是一个代理中间件,它和 Redis 一样也使用 Redis 协议对外提供服务,当客户端向 Codis 发送指令时,Codis 负责将指令转发到后面的 Redis 实例来执行,并将返回结果再转回给客户端。

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

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

因为 Codis 是无状态的,它只是一个转发代理中间件,这意味着我们可以启动多个 Codis 实例,供客户端使用,每个 Codis 节点都是对等的。因为单个 Codis 代理能支撑的 QPS 比较有限,通过启动多个 Codis 代理可以显著增加整体的 QPS 需求,还能起到容灾功能,挂掉一个 Codis 代理没关系,还有很多 Codis 代理可以继续服务。

img
img

Codis 分片原理

Codis 要负责将特定的 key 转发到特定的 Redis 实例,那么这种对应关系 Codis 是如何管理的呢?

Codis 将所有的 key 默认划分为 1024 个槽位(slot),它首先对客户端传过来的 key 进行 crc32 运算计算哈希值,再将 hash 后的整数值对 1024 这个整数进行取模得到一个余数,这个余数就是对应 key 的槽位。

img
img

每个槽位都会唯一映射到后面的多个 Redis 实例之一,Codis 会在内存维护槽位和 Redis 实例的映射关系。这样有了上面 key 对应的槽位,那么它应该转发到哪个 Redis 实例就很明确了。

py复制代码hash = crc32(command.key)
slot_index = hash % 1024
redis = slots[slot_index].redis
redis.do(command)

槽位数量默认是1024,它是可以配置的,如果集群节点比较多,建议将这个数值配置大一些,比如2048、4096。

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

如果 Codis 的槽位映射关系只存储在内存里,那么不同的 Codis 实例之间的槽位关系就无法得到同步。所以 Codis 还需要一个分布式配置存储数据库专门用来持久化槽位关系。Codis 开始使用 ZooKeeper,后来连 etcd 也一块支持了。

img
img

Codis 将槽位关系存储在 zk 中,并且提供了一个 Dashboard 可以用来观察和修改槽位关系,当槽位关系变化时,Codis Proxy 会监听到变化并重新同步槽位关系,从而实现多个 Codis Proxy 之间共享相同的槽位关系配置。

扩容

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

那 Codis 如何找到槽位对应的所有 key 呢?

Codis 对 Redis 进行了改造,增加了 SLOTSSCAN 指令,可以遍历指定 slot 下所有的 key。Codis 通过 SLOTSSCAN 扫描出待迁移槽位的所有的 key,然后挨个迁移每个 key 到新的 Redis 节点。

在迁移过程中,Codis 还是会接收到新的请求打在当前正在迁移的槽位上,因为当前槽位的数据同时存在于新旧两个槽位中,Codis 如何判断该将请求转发到后面的哪个具体实例呢?

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

ini复制代码slot_index = crc32(command.key) % 1024
if slot_index in migrating_slots:
	do_migrate_key(command.key)  # 强制执行迁移
	redis = slots[slot_index].new_redis
else:
	redis = slots[slot_index].redis
redis.do(command)

我们知道 Redis 支持的所有 Scan 指令都是无法避免重复的,同样 Codis 自定义的 SLOTSSCAN 也是一样,但是这并不会影响迁移。因为单个 key 被迁移一次后,在旧实例中它就彻底被删除了,也就不可能会再次被扫描出来了。

自动均衡

Redis 新增实例,手工均衡slots太繁琐,所以 Codis 提供了自动均衡功能。自动均衡会在系统比较空闲的时候观察每个 Redis 实例对应的 Slots 数量,如果不平衡,就会自动进行迁移。

Codis 的代价

Codis 给 Redis 带来了扩容的同时,也损失了其它一些特性。因为 Codis 中所有的 key 分散在不同的 Redis 实例中,所以事务就不能再支持了,事务只能在单个 Redis 实例中完成。同样 rename 操作也很危险,它的参数是两个 key,如果这两个 key 在不同的 Redis 实例中,rename 操作是无法正确完成的。Codis 的官方文档中给出了一系列不支持的命令列表。

同样为了支持扩容,单个 key 对应的 value 不宜过大,因为集群的迁移的最小单位是 key,对于一个 hash 结构,它会一次性使用 hgetall 拉取所有的内容,然后使用 hmset 放置到另一个节点。如果 hash 内部的 kv 太多,可能会带来迁移卡顿。官方建议单个集合结构的总字节容量不要超过 1M。如果我们要放置社交关系数据,例如粉丝列表这种,就需要注意了,可以考虑分桶存储,在业务上作折中。

Codis 因为增加了 Proxy 作为中转层,所有在网络开销上要比单个 Redis 大,毕竟数据包多走了一个网络节点,整体在性能上要比单个 Redis 的性能有所下降。但是这部分性能损耗不是太明显,可以通过增加 Proxy 的数量来弥补性能上的不足。

Codis 的集群配置中心使用 zk 来实现,意味着在部署上增加了 zk 运维的代价,不过大部分互联网企业内部都有 zk 集群,可以使用现有的 zk 集群使用即可。

Codis 的优点

Codis 在设计上相比 Redis Cluster 官方集群方案要简单很多,因为它将分布式的问题交给了第三方 zk/etcd 去负责,自己就省去了复杂的分布式一致性代码的编写维护工作。而 Redis Cluster 的内部实现非常复杂,它为了实现去中心化,混合使用了复杂的 Raft 和 Gossip 协议,还有大量的需要调优的配置参数,当集群出现故障时,维护人员往往不知道从何处着手。

MGET 指令的操作过程

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

架构变迁

Codis 作为非官方 Redis 集群方案,近几年来它的结构一直在不断变化,一方面当官方的 Redis 有变化的时候它要实时去跟进,另一方面它作为 Redis Cluster 的竞争方案之一,它还得持续提高自己的竞争力,给自己增加更多的官方集群所没有的便捷功能。

比如 Codis 有个特色的地方在于强大的 Dashboard 功能,能够便捷地对 Redis 集群进行管理。这是 Redis 官方所欠缺的。另外 Codis 还开发了一个 Codis-fe(federation 联邦) 工具,可以同时对多个 Codis 集群进行管理。在大型企业,Codis 集群往往会有几十个,有这样一个便捷的联邦工具可以降低不少运维成本。

Codis 的尴尬

Codis 不是 Redis 官方项目,这意味着它的命运会无比曲折,它总是要被官方 Redis 牵着牛鼻子走。当 Redis 官方提供了什么功能它欠缺时,Codis 就会感到恐惧,害怕自己被市场甩掉,所以必须实时保持跟进。

同时因为 Codis 总是要比 Redis 官方慢一拍,Redis 官方提供的最新功能,Codis 往往要等很久才能同步。比如现在 Redis 已经进入到 4.0 阶段,提供了插件化 Redis-Module 支持,目前 Codis 还没有提供解决方案。

现在 Redis-Cluster 在业界已经逐渐流行起来,Codis 能否持续保持竞争力是个问题,我们看到 Codis 在不断的差异化竞争,竞争的方法就体现在工具上,而不是内核,这个和官方的路线真是相反的,官方对工具无暇顾及,只提供基本的工具,其它完全交给第三方去开发。

Codis 的后台管理

后台管理的界面非常友好,使用了最新的 BootStrap 前端框架。比较酷炫的是可以看到实时的 QPS 波动曲线。

img
img

同时还支持服务器集群管理功能,可以增加分组、增加节点、执行自动均衡等指令,还可以直接查看所有 slot 的状态,每个 slot 被分配到哪个 Redis 实例。

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/847157.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何调教让chatgpt读取自己的数据文件(保姆级图文教程)

提示:如何调教让chatgpt读取自己的数据文件(保姆级图文教程) 文章目录 前言一、如何投喂自己的数据?二、调教步骤总结 前言 chatgpt提示不能读取我们提供的数据文件,我们应该对它进行调教。 一、如何投喂自己的数据? 让chatgpt读…

干货分享 | TSMaster图形模块功能详解(二)—— 以CAN信号为例

在上一章节中,我们主要分享了TSMaster图形模块功能中信号的导入与删除、图形分栏、暂停与启动和禁止图形、高亮信号相关操作、预设、信号与数据的导入与导出6大模块的操作教程。 本章节在上一篇基础上,继续介绍TSMaster图形模块功能第7~10模块的教程。 本…

解决Redis启动时闪退 报错Creating Server TCP listening socket *:6379: bind: No error

找到安装redis的文件夹 在地址输入cmd 依次输入如下 redis-cli.exe shutdown exit redis-server.exe redis.windows.conf

数据结构---跳表

目录标题 为什么会有跳表跳表的原理跳表的模拟实现准备工作find函数insert函数erase函数 测试效率比较 为什么会有跳表 在前面的学习过程中我们学习过链表这个容器,这个容器在头部和尾部插入数据的时间复杂度为O(1),但是该容器存在一个缺陷就是不管数据…

sysstat安装与使用

官方文档 http://sebastien.godard.pagesperso-orange.fr/documentation.html sysstat安装 1.下载源码 https://github.com/sysstat/sysstat 2.编译安装 tar xvf sysstat-xxx.tar.gz ./configure make -j 16 make install3.测试 iostatsysstat使用 sysstat 包包含许多商…

基于Flask的模型部署

基于Flask的模型部署 一、背景 Flask:一个使用Python编写的轻量级Web应用程序框架; 首先需要明确模型部署的两种方式:在线和离线; 在线:就是将模型部署到类似于服务器上,调用需要通过网络传输数据&…

css小练习:案例6.炫彩加载

一.效果浏览图 二.实现思路 html部分 HTML 写了一个加载动画效果&#xff0c;使用了一个包含多个 <span> 元素的 <div> 元素&#xff0c;并为每个 <span> 元素设置了一个自定义属性 --i。 这段代码创建了一个简单的动态加载动画&#xff0c;由20个垂直排列的…

ESD接地实时监控系统有哪些功能

ESD接地实时监控系统是一种用于监测和维护静电放电&#xff08;ESD&#xff09;接地的设备和软件系统。静电放电事件可能会对敏感电子元件、设备或工作环境造成损害&#xff0c;因此对ESD接地进行有效的监控至关重要。 ESD接地实时监控系统主要包括以下几个方面的功能&#xf…

第五次作业 运维高级 构建 LVS-DR 集群和配置nginx负载均衡

1、基于 CentOS 7 构建 LVS-DR 群集。 LVS-DR模式工作原理 首先&#xff0c;来自客户端计算机CIP的请求被发送到Director的VIP。然后Director使用相同的VIP目的IP地址将请求发送到集群节点或真实服务器。然后&#xff0c;集群某个节点将回复该数据包&#xff0c;并将该数据包…

成功解决ubuntu-22.04的sudo apt-get update一直卡在【0% [Waiting for headers]】

成功解决ubuntu-22.04的sudo apt-get update一直卡在【0% [Waiting for headers]】 问题描述解决方案 问题描述 在下载安装包的时候一直卡在0% [Waiting for headers]&#xff0c;报错信息如下&#xff1a; Get:1 file:/var/cudnn-local-repo-ubuntu1804-8.5.0.96 InRelease […

中科驭数亮相DPU峰会,分享HADOS软件生态实践和大数据计算方案,再获评“匠芯技术奖”

又是一年相逢时&#xff0c;8月4日&#xff0c;第三届DPU峰会在北京开幕&#xff0c;本届峰会由中国通信学会指导&#xff0c;江苏省未来网络创新研究院主办&#xff0c;SDNLAB社区承办&#xff0c;以“智驱创新芯动未来”为主题&#xff0c;沿袭技术创新、生态协同的共创效应&…

vue 路由页面跳转

从index.vue跳转到data.vue index.vue <el-table-column label"客户数" align"center" :show-overflow-tooltip"true"><template slot-scope"scope"><router-link :to"/system/enterprise-data/index/ scope.ro…

人工智能术语翻译(五)

文章目录 摘要QRST 摘要 人工智能术语翻译第五部分&#xff0c;包括Q、R、S、T开头的词汇&#xff01; Q 英文术语中文翻译常用缩写备注Q FunctionQ函数Q-LearningQ学习Q-NetworkQ网络Quadratic Loss Function平方损失函数Quadratic Programming二次规划Quadrature Pair象限…

NSS [MoeCTF 2022]baby_file

NSS [MoeCTF 2022]baby_file 题目源码直接给了 使用data伪协议发现被ban了。 那就换一种伪协议php://filter&#xff0c;猜测flag在同目录下flag.php中或根目录下/flag中 php://filter/readconvert.base64-encode/resourceflag.php读取文件源码&#xff08;针对php文件需要ba…

华为路由器:IPSec加密GRE通道(GRE over IPsec)

IPSec加密GRE通道 由于GRE隧道不提供安全性保障&#xff0c;使用ipsec加密gre隧道是现网中比较常用的VPN部署&#xff0c;它的加密方式分为两种&#xff1a; 可以使用IPsec来加密隧道进行传输&#xff0c;叫做IPsec over GRE&#xff1b; 加密数据流后从隧道传输&#xff0c;…

OLED透明屏拼缝技术:创新的显示解决方案

引言&#xff1a;OLED透明屏作为一种创新的显示技术&#xff0c;已经在各个领域展现出了巨大的潜力。而其中的拼缝技术更是为OLED透明屏的应用带来了全新的可能性。 对此&#xff0c;尼伽便大家具体介绍一下OLED透明屏拼缝技术的概念、优势以及应用领域&#xff0c;并探讨其在…

Git仓关联多个远程仓路径

前言 Git仓如果需要将代码push到多个仓&#xff0c;常用的做法是添加多个远程仓路径&#xff0c;然后分别push。这样虽然可以实现目的&#xff0c;但是需要多次执行push指令&#xff0c;很麻烦。 本文介绍关联多个远程仓路径且执行一次push指令的方法&#xff1a;git remote …

python教学资源百度网盘,python教程百度网盘资源

大家好&#xff0c;本文将围绕最全python教程百度网盘分享展开说明&#xff0c;python教程百度网盘资源是一个很多人都想弄明白的事情&#xff0c;想搞清楚python教学资源百度网盘需要先了解以下几个事情。 Python在近几年越来越受追捧&#xff0c;很多童鞋或者职场小伙伴想要提…

PotPlayer播放时、拖动播放条,CPU占用率高、卡顿

鼠标右击播放界面&#xff0c;滤镜/解码器管理 > 视频解码器 > 内置解码器/DXVA设置 > 勾选使用硬件加速&#xff0c;确定&#xff0c;关闭播放器再重新打开即可&#xff1b; 其他播放软件同理。 高级设置&#xff1a;https://www.hao4k.cn/thread-26475-1-1.html

【车道线】TwinLiteNet 复现过程全纪录

目录 1、下载代码 2、解压缩 3、建立conda环境 4、验证环境 5、复制环境 6、安装依赖 7、测试 1、下载代码 代码地址&#xff1a;https://github.com/chequanghuy/TwinLiteNet 2、解压缩 3、建立conda环境 我个人先建立起一个基础环境&#xff0c;然后复制为twinlitenet…