Redis Cluster原理初步
目录
7. 计算key所在slot(cluster.c:keyHashSlot)
2
1. 前言
截至2016/5/16最新版本的redis-3.2.0仍然非强一致性,基于性能考虑master和它的slaves间数据是异步复制的。另外,一个确定的key总是只会落到确定的master,除非使用redis-trib.rb等工具修改slots和master间的绑定关系,目前的redis cluste不支持自动从一个master迁移一个slot到另一个master(slaves对slots来说,可以认为和对应的master相同)。
2. 槽(slots)
Redis cluster将所有存储在其上的key通过一个hash算法划分成若干slots,当前为个slots,值在cluster.h文件中由宏CLUSTER_SLOSTS指定。
3. 路由配置(node.conf)
存储的内容和redis命令“cluster nodes”的输出相同,即存储了master和slave信息,以及各master存储的slots,亦即slots的路由信息存储在node.conf。
同一Redis cluster中的所有节点的node.conf文件内容最终是一致的。
4. 总slots数(cluster.h:16384)
#define CLUSTER_SLOTS // 等于(0x3FFF + 1) |
宏CLUSTER_SLOTS定义了redis cluster的slots数,理论上这个值应当可以修改重编译。其值越大,相对更容易均衡,可支撑更多节点数的集群(实际受限于无中心节点,当然架构的redis cluster节点数不宜过大,否则可能引起网络风暴)。
5. key的路由
-> 将key转成整数值
-> 计算key所在的slot
-> 找到slot所在的master或slaves(redis cluster可配置允许slaves提供读)
-> 转成直接对master或slaves的请求。
由于任何一个redis cluster节点都存储了相同内容的node.conf,所以client可以请求任一节点获得slots的路由数据。
而且由于node.conf中包含了master和slaves信息,因此读写操作可以完美的路由到相应的节点。
6. 将key转成整数值(crc16.c:crc16)
Redis使用crc算法将一个字符串转成整数,宏CLUSTER_SLOTS的值是不能超过CRC返回的最大值。
uint16_t crc16(const char *buf, int len) { int counter; uint16_t crc = 0; for (counter = 0; counter < len; counter++) crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *buf++)&0x00FF]; return crc; } |
7. 计算key所在slot(cluster.c:keyHashSlot)
对于一个redis KEY它归属于哪一个slot,这个可以通过函数keyHashSlot()调用计算出来:
unsigned int keyHashSlot(char *key, int keylen) { int s, e; /* start-end indexes of { and } */ for (s = 0; s < keylen; s++) if (key[s] == '{') break; /* No '{' ? Hash the whole key. This is the base case. */ if (s == keylen) return crc16(key,keylen) & 0x3FFF; /* '{' found? Check if we have the corresponding '}'. */ for (e = s+1; e < keylen; e++) if (key[e] == '}') break; /* No '}' or nothing betweeen {} ? Hash the whole key. */ if (e == keylen || e == s+1) return crc16(key,keylen) & 0x3FFF; /* If we are here there is both a { and a } on its right. Hash * what is in the middle between { and }. */ return crc16(key+s+1,e-s-1) & 0x3FFF; // 3FFF即为16383 } |
8. Redis Cluster Client实现
通过上面的信息,不然发现,Redis Cluster Client只是在原来单机版client基础上多了一层薄的路由逻辑。因此可以基于现有的hiredis等实现支持redis cluster的client库。大致过程如下:
class CRedisClusterClient { public: // nodes Redis集群中的单个或多个节点,格式为:ip1:port1,ip2:port2,如:127.0.0.1:6379,127.0.0.1:6380,192.168.31.11:6379 CRedisClusterClient(const std::string& nodes); void set(const std::string& key, const std::string& value) const; void get(const std::string& key, std::string* value); private: redisContext* _redis_context; // hiredis }; |
set()函数实现:
1) CRedisClusterClient从nodes取任一nodeA,如:127.0.0.1:6380
2) 建立与nodeA的连接
3) 从nodeA取得slots路由数据(实现时可缓存这部分数据,以提升性能)
4) 构造slots路由数据表(由于slots总数有限,可以以slot为下标数组方式组织路由表)
5) 计算key所在的slot
6) 找到slot所在的nodeB(对于写操作,要求nodeB为master,有可能碰巧就是nodeA)
7) 使用hiredis访问nodeB(从这步开始和原使用hiredis相同)
8) 取得hiredis返回的结果
如果使用hiredis发生网络异常,对于写操作从第3步开始重执行,对于读操作从第6步重选一个node重执行。
Redis Cluster原理初步的更多相关文章
- 全面剖析Redis Cluster原理和应用
全面剖析Redis Cluster原理和应用 1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最 ...
- Redis Cluster 原理相关说明
背景 之前写的 Redis Cluster部署.管理和测试 和 Redis 5.0 redis-cli --cluster help说明 已经比较详细的介绍了如何安装和维护Cluster.但关于Clu ...
- Redis Cluster 原理说的头头是道,这些配置不懂就是纸上谈兵
Redis Cluster 原理说的头头是道,这些配置不懂就是纸上谈兵 Redis Cluster 集群相关配置,使用集群方式的你必须重视和知晓.别嘴上原理说的头头是道,而集群有哪些配置?如何配置让集 ...
- 全面剖析Redis Cluster原理和应用 (转)
1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最核心的目标有三个: 性能:这是Redis赖以生 ...
- 全面剖析Redis Cluster原理和应用 (good)
redis redis cluster注意的问题 : 1.‘cluster-require-full-coverage’参数的设置.该参数是redis配置文件中cluster模式的一个参数,从字面上基 ...
- 深度图解Redis Cluster原理
不想谈好吉他的撸铁狗,不是好的程序员,欢迎微信关注「SH的全栈笔记」 前言 上文我们聊了基于Sentinel的Redis高可用架构,了解了Redis基于读写分离的主从架构,同时也知道当Redis的ma ...
- Redis Cluster原理
Redis Cluster 是Redis的集群实现,内置数据自动分片机制,集群内部将所有的key映射到16384个Slot中,集群中的每个Redis Instance负责其中的一部分的Slot的读写. ...
- Redis Cluster部署、管理和测试
背景: Redis 3.0之后支持了Cluster,大大增强了Redis水平扩展的能力.Redis Cluster是Redis官方的集群实现方案,在此之前已经有第三方Redis集群解决方案,如Twen ...
- Redis Cluster架构优化
Redis Cluster架构优化 在<全面剖析Redis Cluster原理和应用>中,我们已经详细剖析了现阶段Redis Cluster的缺点: 无中心化架构 Gossip消息的开销 ...
随机推荐
- MySql重复查询
MYSQL查询重复记录的方法很多,下面就为您介绍几种最常用的MYSQL查询重复记录的方法,希望对您学习MYSQL查询重复记录方面能有所帮助. 1.查找表中多余的重复记录,重复记录是根据单个字段(peo ...
- COM组件 IDispatch 及双接口的调用
转自:http://blog.csdn.net/cnhk1225/article/details/50555647 一.前言 前段时间,由于工作比较忙,没有能及时地写作.其间收到了很多网友的来信询问和 ...
- FP-growth算法高效发现频繁项集(Python代码)
FP-growth算法高效发现频繁项集(Python代码) http://blog.csdn.net/leo_xu06/article/details/51332428
- oracle与DB2
1.体系结构,DB2的实例和数据库分开的做法,我个人还是比较喜欢的,因为实例可以创建多个,数据库的恢复直接恢复到实例下就可以了,相对ORACLE简单多了. 2.管理工具,DB2的管理工具做得太简陋了, ...
- yum 操作
一.使用yum安装和卸载软件,有个前提是yum安装的软件包都是rpm格式的. 安装的命令是,yum install ~,yum会查询数据库,有无这一软件包,如果有,则检查其依赖冲突关系,如果没有依赖冲 ...
- idea 打包java程序
创建maven项目 在pom.xml中添加: <build> <plugins> <plugin> <groupId>org.apache.maven. ...
- Js获取iframe子页面全局变量
项目中通过iframe内嵌了一个子页面,子页面定义了一些全局变量,父页面需要获取子页面的全局变量,做了一些测试(我的环境IE10和Firefox32.0.3),得出如下结论: IE下: window. ...
- struts2标签类别
要在jsp中使用Struts2的标志,先要指明标志的引入.通过jsp的代码的顶部加入以下的代码: <%@taglib prefix="s" uri="/struts ...
- ReportViewer工具栏功能扩展[手动设置打印/导出按钮]
ReportViewer在IE11后打印按钮就存在兼容问题,火狐,谷歌也存在打印按钮显示的兼容性问题,本资料就是解决ReportViewer打印按钮显示的问题, 通过自己写脚本添加到DOM里面让所有浏 ...
- 【校招面试 之 C/C++】第3题 为什么要内存对齐?以及内存对齐的方式
1.为什么要进行内存对? 参考:https://blog.csdn.net/a369000753/article/details/51188915 所谓内存对齐,是为了让内存存取更有效率而采用的一种编 ...