Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value

时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,

这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大

致均等的将哈希槽映射到不同的节点。

Redis 集群没有使用一致性hash, 而是引入了哈希槽的概念。

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽。这种结构很容易添加或者删除节点,并且无论是添加删除或者修改某一个节点,都不会造成集群不可用的状态。

使用哈希槽的好处就在于可以方便的添加或移除节点。

当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;

当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了;

在这一点上,我们以后新增或移除节点的时候不用先停掉所有的 redis 服务。

"用了哈希槽的概念,而没有用一致性哈希算法,不都是哈希么?这样做的原因是为什么呢?"
Redis Cluster是自己做的crc16的简单hash算法,没有用一致性hash。Redis的作者认为它的crc16(key) mod 16384的效果已经不错了,虽然没有一致性hash灵活,但实现很简单,节点增删时处理起来也很方便。

"为了动态增删节点的时候,不至于丢失数据么?"
节点增删时不丢失数据和hash算法没什么关系,不丢失数据要求的是一份数据有多个副本。

“还有集群总共有2的14次方,16384个哈希槽,那么每一个哈希槽中存的key 和 value是什么?”
当你往Redis Cluster中加入一个Key时,会根据crc16(key) mod 16384计算这个key应该分布到哪个hash slot中,一个hash slot中会有很多key和value。你可以理解成表的分区,使用单节点时的redis时只有一个表,所有的key都放在这个表里;

改用Redis Cluster以后会自动为你生成16384个分区表,你insert数据时会根据上面的简单算法来决定你的key应该存在哪个分区,每个分区里有很多key。

[架构描述]

redis

组件版本:

redis:5.0.8

节点架构:

3主3从、6主机

扩容后架构:

6主6从、12主机

[问题描述]

Redis(RemoteDictionary Server ),即远程字典服务,是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

redis是一个key-value存储系统,支持存储的value类型包括string(字符串)、list(链表)、set(集合)、zset(sortedset--有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

某业务系统采用rediscluster架构,由于数据量的增长导致部分数据还未过期时就被redis最大内存限制给删除掉,所以业务在当前三柱三从架构无法满足业务数据量持续增长的情况,需要扩容节点至六主六从。

[结构及详细说明]

Redis集群大致架构图:

一组RedisCluster是由多个Redis实例组成,官方推荐使用6实例,其中3个为主节点,3个为从结点。一旦有主节点发生故障的时候,RedisCluster可以选举出对应的从结点成为新的主节点,继续对外服务,从而保证服务的高可用性。那么对于客户端来说,知道知道对应的key是要路由到哪一个节点呢?原来,RedisCluster把所有的数据划分为16384个不同的槽位,可以根据机器的性能把不同的槽位分配给不同的Redis实例,对于Redis实例来说,他们只会存储部门的Redis数据,当然,槽的数据是可以迁移的,不同的实例之间,可以通过一定的协议,进行数据迁移。

需要把3主3从扩容为6主6从,就需要增加6个节点,依次添加3个主节点hash槽,再添加3个从节点手动分配给主节点。

[操作过程]

1、创建节点

复制原有集群节点的配置文件更改端口目录等然后再启动redis,要添加6个节点需创建6个节点并启动:

./redis-server../6001/redis.conf

./redis-server../6002/redis.conf

./redis-server../6003/redis.conf

./redis-server../6004/redis.conf

./redis-server../6005/redis.conf

./redis-server../6006/redis.conf

2、添加主节点

第一个ip:port为需要添加的节点ip和端口,第二个ip:port为当前集群中的节点和端口;先后执行以下命令:

./redis-cli--cluster add-node 192.168.8.20:6001 192.168.8.10:7001 -a 123456

./redis-cli--cluster add-node 192.168.8.21:7002 192.168.8.10:7001 -a 123456

……

3、分配hash槽

新添加的节点没有哈希槽,并不能正常存储数据,需要给新添加的节点分配哈希槽。

  1. 重新分配哈希槽

./redis-cli--cluster reshard  ip:port -a passwd

  1. 输入要分配多少个哈希槽(数量)

  1. 输入指定要分配哈希槽的节点ID

  1. 选择需要分配的哈希槽来源

输入all需要分配给目标节点的哈希槽来着当前集群的其他主节点(每个节点拿出的数量为集群自动决定)

分配哈希槽有两种方式

(1)将所有节点用作哈希槽的源节点。

(2)在指定的节点拿出指定数量的哈希槽分配到目标节点:

4、添加从节点

添加6004节点(slave的添加方法,master为7004)

#节点ID是主节点的ID

#192.168.8.20:6004 是新加的从节点

#192.168.8.10:7004 作为从节点的主节点

./redis-cli--cluster add-node --cluster-slave --cluster-master-idxxxxxxxxxxxxxxxxxxx 192.168.8.20:6004 192.168.8.10:7004

[总结]

1、redis扩容一般有两种方法,一种是在线扩容,一种是离线扩容,从业务的角度来说,在线扩容是最方便的方法,但在线扩容有个问题是,过程中如果某个槽正在操作会导致迁移槽是发送错误,需要人工干预。

2、离线扩容是比较快速的方法,人工干预比较少由集群自动分配哈希槽,缺点是需停掉业务。

3、一般来说业务上线前会对redis缓存数据量有一个预估,从而对架构的硬件配置有个预估,就不会产生扩容这个操作,但往往业务数据量是一个动态的,无法预估的,所以需要通过扩容节点的操作慢在业务的需求,需要保证扩容过程正保证数据的正确性。

 

Redis集群节点扩容及其 Redis 哈希槽的更多相关文章

  1. 超详细,多图文介绍redis集群方式并搭建redis伪集群

    超详细,多图文介绍redis集群方式并搭建redis伪集群 超多图文,对新手友好度极好.敲命令的过程中,难免会敲错,但为了截好一张合适的图,一旦出现一点问题,为了好的演示效果,就要从头开始敲.且看且珍 ...

  2. redis集群节点宕机

    redis集群是有很多个redis一起工作,那么就需要这个集群不是那么容易挂掉,所以呢,理论上就应该给集群中的每个节点至少一个备用的redis服务.这个备用的redis称为从节点(slave). 1. ...

  3. redis集群节点重启后恢复

    服务器重启后,集群报错: [root@SHH-HQ-NHS11S nhsuser]# redis-cli -c -h ip -p 7000ip:7000> set cc dd(error) CL ...

  4. 探索Redis设计与实现13:Redis集群机制及一个Redis架构演进实例

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  5. 最大的Redis集群:新浪Redis集群揭秘

    前言 Tape is Dead,Disk is Tape,Flash is Disk,RAM Locality is King.       — Jim Gray Redis不是比较成熟的Memcac ...

  6. c#+linux+mono+Redis集群(解决无法连接Redis的问题)

    在linux环境中使用mono来执行c#的程序, 在连接redis的时候遇到了无法连接数据库的错误.如下: Unhandled Exception:StackExchange.Redis.RedisC ...

  7. kubesphere集群节点扩容

    原有的节点是 : master[123] , node[1234] 新加的节点node5 一.修改配置文件hosts.ini [root@master0 ~]# /conf/hosts.ini [al ...

  8. Redis集群进阶之路

    Redis集群规范 本文档基于Redis 3.X或更高版本,讲解Redis集群算法以及设计原理.此官方文档长期更新且随着Redis新版本特性的变化变动,详细请留意官网. 官网地址:https://re ...

  9. [个人翻译]Redis 集群教程(上)

    官方原文地址:https://redis.io/topics/cluster-tutorial  水平有限,如果您在阅读过程中发现有翻译的不合理的地方,请留言,我会尽快修改,谢谢.        这是 ...

随机推荐

  1. SpringMVC的web配置

    之前并没有意愿写关于下面内容的小作文.因为总结SPI相关的标准(SPI机制之JDK中的SPI - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)),而这个也是关于标准的,Servlet3.0 ...

  2. 图解python | 循环与控制

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/56 本文地址:http://www.showmeai.tech/article-det ...

  3. spring循环依赖的产生与解决

    1.循环依赖的产生 在spring中对象默认都是单例的 ,意味整个容器中只有一个该类的对象. 如图,B类有一个属性a,A类有一个属性b.当B类创建对象时,要给a属性赋值:当A类创建对象时,要给b属性赋 ...

  4. java 接口 文件传输

    调用接收端 @ApiOperation(value = "文件请求展示方法") @RequestMapping(value = "/showFile", met ...

  5. qt日常积累

    http://blog.sina.com.cn/s/blog_b8bcba160102yyi3.html

  6. Python脚本生成可执行文件&(恋爱小脚本)

    Python脚本生成可执行文件&(恋爱小脚本) 参考文献: http://c.biancheng.net/view/2690.html; https://blog.csdn.net/qq_39 ...

  7. 基于Kubernetes/K8S构建Jenkins持续集成平台(上)-1

    基于Kubernetes/K8S构建Jenkins持续集成平台(上)-1 Jenkins的Master-Slave分布式构建 什么是Master-Slave分布式构建 Jenkins的Master-S ...

  8. Lua中如何实现类似gdb的断点调试--03通用变量修改及调用栈回溯

    在前面两篇01最小实现及02通用变量打印中,我们已经实现了设置断点.删除断点及通用变量打印接口. 本篇将继续新增两个辅助的调试接口:调用栈回溯打印接口.通用变量设置接口.前者打印调用栈的回溯信息,后者 ...

  9. 【面经】Java面试突击

    基础语法 基本数据结构 Java 的基本数据类型有 8 种,包括 6 种数字类型.1 种字符类型和 1 种布尔类型. 基本数据类型总览 数字类型包括 4 种整数类型和 2 种浮点数类型,4 种整数类型 ...

  10. linux下的硬盘分区、格式化、挂载

    linux下的MBR(msdos)分区.格式化.挂载 在linux下,需要使用一块硬盘. 需要进行以下四步: 识别硬盘-----分区规划-----格式化-----挂载 步骤一:分区规划 MBR模式分区 ...