redis-5.0.3集群的搭建

        Redis 在3.0版本前只支持单实例模式,虽然支持主从模式、哨兵模式部署来解决单点故障,但是现在互联网企业动辄大几百G的数据,可完全是没法满足业务的需求,所以,Redis 在 3.0 版本以后就推出了集群模式。

        2018年十月 Redis 发布了稳定版本的 5.0 版本,推出了各种新特性,其中一点是放弃 Ruby的集群方式,改为 使用 C语言编写的 redis-cli的方式,是集群的构建方式复杂度大大降低。



        redis是一个开源的key value存储系统,受到了广大互联网公司的青睐。redis3.0版本之前只支持单例模式,在3.0版本及以后才支持集群,我这里用的是redis5.0.3版本;

        redis集群采用P2P模式,是完全去中心化的,不存在中心节点或者代理节点;

        redis集群是没有统一的入口的,客户端(client)连接集群的时候连接集群中的任意节点(node)即可,集群内部的节点是相互通信的(PING-PONG机制),每个节点都是一个redis实例;

        为了实现集群的高可用,即判断节点是否健康(能否正常使用),redis-cluster有这么一个投票容错机制:如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法;

        那么如何判断集群是否挂了呢? -> 如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法;

        那么为什么任意一个节点挂了(没有从节点)这个集群就挂了呢? -> 因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当需要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,然后得到一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪个节点中。所以一旦某个节点挂了,该节点对应的slot就无法使用,那么就会导致集群无法正常工作。

        综上所述,每个Redis集群理论上最多可以有16384个节点。


1、集群的作用:

        集群,即 Redis Cluster,是 Redis 3.0 开始引入的分布式存储方案。集群由多个节点(Node)组成,Redis 的数据分布在这些节点中。

        集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护;从节点只进行主节点数据和状态信息的复制。

        集群的作用,可以归纳为两点:

        1)、数据分区

        数据分区(或称数据分片)是集群最核心的功能。集群将数据分散到多个节点:

                1、一方面突破了 Redis 单机内存大小的限制,存储容量大大增加。

                2、另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。

        Redis 单机内存大小受限问题,在介绍持久化和主从复制时都有提及。

        例如,如果单机内存太大,bgsave 和 bgrewriteaof 的 fork 操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。

        2)、高可用

        集群支持主从复制和主节点的自动故障转移(与哨兵类似),当任一节点发生故障时,集群仍然可以对外提供服务。

        

        本文内容基于 Redis 5.0.3。


2、集群方案设计:

        设计集群方案时,至少要考虑以下因素:

        ①、高可用要求:根据故障转移的原理,至少需要 3 个主节点才能完成故障转移,且 3 个主节点不应在同一台物理机上。

        每个主节点至少需要 1 个从节点,且主从节点不应在一台物理机上;因此高可用集群至少包含 6 个节点。

        ②、数据量和访问量:估算应用需要的数据量和总访问量(考虑业务发展,留有冗余),结合每个主节点的容量和能承受的访问量(可以通过 benchmark 得到较准确估计),计算需要的主节点数量。

        ③、节点数量限制:Redis 官方给出的节点数量限制为 1000,主要是考虑节点间通信带来的消耗。

        在实际应用中应尽量避免大集群,如果节点数量不足以满足应用对 Redis 数据量和访问量的要求,可以考虑:①业务分割,大集群分为多个小集群;②减少不必要的数据;③调整数据过期策略等。

        ④、适度冗余:Redis 可以在不影响集群服务的情况下增加节点,因此节点数量适当冗余即可,不用太大。


        Redis集群方案:

        Redis Cluster 集群模式通常具有 高可用、可扩展性、分布式、容错 等特性。Redis 分布式方案一般有两种:

        2.1 客户端分区方案

        客户端 就已经决定数据会被 存储 到哪个 redis 节点或者从哪个 redis 节点 读取数据。其主要思想是采用 哈希算法 将 Redis 数据的 key 进行散列,通过 hash 函数,特定的 key会 映射 到特定的 Redis 节点上。

        冷暖自知一抹茶ck

        客户端分区方案 的代表为 Redis Sharding,Redis Sharding 是 Redis Cluster 出来之前,业界普遍使用的 Redis 多实例集群 方法。Java 的 Redis 客户端驱动库 Jedis,支持 Redis Sharding 功能,即 ShardedJedis 以及 结合缓存池 的 ShardedJedisPool。

        优点:

                不使用 第三方中间件,分区逻辑 可控,配置 简单,节点之间无关联,容易 线性扩展,灵活性强。

        缺点:

                客户端 无法 动态增删 服务节点,客户端需要自行维护 分发逻辑,客户端之间 无连接共享,会造成 连接浪费。

        2.2. 代理分区方案

        客户端 发送请求到一个 代理组件,代理 解析 客户端 的数据,并将请求转发至正确的节点,最后将结果回复给客户端。

        优点:简化 客户端 的分布式逻辑,客户端 透明接入,切换成本低,代理的 转发 和 存储 分离。

        缺点:多了一层 代理层,加重了 架构部署复杂度 和 性能损耗。

        冷暖自知一抹茶ck

        代理分区 主流实现的有方案有 Twemproxy 和 Codis。

        2.2.1. Twemproxy

        Twemproxy 也叫 nutcraker,是 twitter 开源的一个 redis 和 memcache 的 中间代理服务器 程序。Twemproxy 作为 代理,可接受来自多个程序的访问,按照 路由规则,转发给后台的各个 Redis 服务器,再原路返回。Twemproxy 存在 单点故障 问题,需要结合 Lvs 和 Keepalived 做 高可用方案。

        冷暖自知一抹茶ck

        优点:应用范围广,稳定性较高,中间代理层 高可用。

        缺点:无法平滑地 水平扩容/缩容,无 可视化管理界面,运维不友好,出现故障,不能 自动转移。

        2.2.2. Codis

        Codis 是一个 分布式 Redis 解决方案,对于上层应用来说,连接 Codis-Proxy 和直接连接 原生的 Redis-Server 没有的区别。Codis 底层会 处理请求的转发,不停机的进行 数据迁移 等工作。Codis 采用了无状态的 代理层,对于 客户端 来说,一切都是透明的。

        冷暖自知一抹茶ck

        优点 : 实现了上层 Proxy 和底层 Redis 的 高可用,数据分片 和 自动平衡,提供 命令行接口 和 RESTful API,提供 监控 和 管理 界面,可以动态 添加 和 删除 Redis 节点。

        缺点 : 部署架构 和 配置 复杂,不支持 跨机房 和 多租户,不支持 鉴权管理。

        2.3. 查询路由方案

        客户端随机地 请求任意一个 Redis 实例,然后由 Redis 将请求 转发 给 正确 的 Redis 节点。Redis Cluster 实现了一种 混合形式 的 查询路由,但并不是 直接 将请求从一个 Redis 节点 转发 到另一个 Redis 节点,而是在 客户端 的帮助下直接 重定向( redirected)到正确的 Redis 节点。        

        冷暖自知一抹茶ck

        优点 :无中心节点,数据按照 槽 存储分布在多个 Redis 实例上,可以平滑的进行节点 扩容/缩容,支持 高可用 和 自动故障转移,运维成本低。

        缺点 :严重依赖 Redis-trib 工具,缺乏 监控管理,需要依赖 Smart Client (维护连接,缓存路由表,MultiOp 和 Pipeline 支持)。Failover 节点的 检测过慢,不如 中心节点 ZooKeeper 及时。Gossip 消息具有一定开销。无法根据统计区分 冷热数据。


3、集群搭建:

        一、搭建目的。

            测试我们选择2台服务器,分别为:192.168.142.128,192.168.142.140   每台服务器有3个节点。

            演示在两台机器上搭建3主3从的redis集群,通过演示了解redis集群的搭建,使用和注意事项。

        二、搭建说明

            1、redis-5.0.3版本的redis集群的搭建;

            2、两台机器搭建3主3从的集群;

            3、使用端口7111~7116,集群端口为端口前+1,如果使用端口7111,则其集群通信端口为17111;

                redis.config的配置如下:

冷暖自知一抹茶ck

            4、需要打开7111~7116、17111~17116一共12个端口


        三、搭建过程

        1)、我先在 192.168.142.128 创建3个节点:192.168.142.128

[root@localhost ~]# cd /usr/local/src/redis-5.0.3/
[root@localhost ~]# cp redis.conf ./cluster7111_redis.conf
[root@localhost ~]# cp redis.conf ./cluster7112_redis.conf
[root@localhost ~]# cp redis.conf ./cluster7113_redis.conf

        2)、分别对7111,7112、7113文件夹中的3个文件修改对应的配置,依次修改对应配置文件内容

[root@localhost redis-5.0.3]# vim cluster7111_redis.conf 

daemonize yes                  #redis后台运行
port 7111                    #端口 7111,7112,7113    
pidfile /var/run/redis7111.pid          #pidfile文件对应 7111,7112,7113
logfile "/var/run/redis7111.log"         #集群的配置  配置文件首次启动自动生成 7111,7112,7113
cluster-enabled    yes            #启动集群服务
cluster-config-file /var/run/nodes-7111.conf   #集群配置文件 注意不同端口节点修改不同文件名称;这个文件是Redis集群节点自动持久化每次配置的改变,为了在启动的时候重新读取它。
cluster-node-timeout 5000            #集群节点超时是指一个节点必须达到的毫秒数(请求超时,设置5秒够了)
            
appendonly  yes                 #aof日志开启  有需要就开启,它会每次写操作都记录一条日志


注意:
    ①将绑定的ip地址端口号,注释掉
    #bind 127.0.0.1
    ②由于Linux上的redis处于安全保护模式,这就让你无法从虚拟机外部去轻松建立连接,这里就有两种解决方法,一种是在redis.conf
中设置保护模式为no,   或者是加上安全认证,即redis默认是没有密码的可以直接登录
    protected-mode no

        cluster-enabledyes:Redis 实例可以分为单机模式(standalone)和集群模式(cluster);cluster-enabledyes 可以启动集群模式。


        cluster-config-file:该参数指定了集群配置文件的位置。每个节点在运行过程中,会维护一份集群配置文件。

        每当集群信息发生变化时(如增减节点),集群内所有节点会将最新信息更新到该配置文件。

        当节点重启后,会重新读取该配置文件,获取集群信息,可以方便的重新加入到集群中。

        也就是说,当 Redis 节点以集群模式启动时,会首先寻找是否有集群配置文件。

        如果有则使用文件中的配置启动;如果没有,则初始化配置并将配置保存到文件中。集群配置文件由 Redis 节点维护,不需要人工修改。


        3)、在 192.168.142.130 创建3个节点:对应的端口改为7113,7114,7115.配置对应的改一下就可以了。

[root@localhost ~]# cd /usr/local/src/redis-5.0.3/
[root@localhost ~]# cp redis.conf ./cluster7111_redis.conf
[root@localhost ~]# cp redis.conf ./cluster7112_redis.conf
[root@localhost ~]# cp redis.conf ./cluster7113_redis.conf

        4)、两台机启动各节点(两台服务器方式一样)

[root@localhost ~]# cd /usr/local/src/redis-5.0.3/src/
            
[root@localhost src]# redis-server ../cluster7111_redis.conf 
[root@localhost src]# redis-server ../cluster7112_redis.conf 
[root@localhost src]# redis-server ../cluster7113_redis.conf
[root@localhost src]# redis-server ../cluster7114_redis.conf 
[root@localhost src]# redis-server ../cluster7115_redis.conf 
[root@localhost src]# redis-server ../cluster7116_redis.conf

        5)、查看服务(查看是否启动成功)

[root@localhost src]# ps -ef |grep redis            ##查看192.168.142.128
root       8057      1  0 16:54 ?        00:00:02 redis-server *:7111 [cluster]
root       8062      1  0 16:54 ?        00:00:01 redis-server *:7112 [cluster]
root       8067      1  0 16:54 ?        00:00:01 redis-server *:7113 [cluster]
root      11186   7840  0 17:15 pts/0    00:00:00 grep --color=auto redis

[root@localhost run]# ps -ef |grep redis            ##查看192.168.142.130
root       7994      1  0 17:19 ?        00:00:00 redis-server *:7114 [cluster]
root       8007      1  0 17:19 ?        00:00:01 redis-server *:7115 [cluster]
root       8012      1  0 17:19 ?        00:00:01 redis-server *:7116 [cluster]
root       8140   7814  0 17:29 pts/0    00:00:00 grep --color=auto redis

        6)、7111~7116 服务启动成功后,使用5.0特有的redis-cli功能开启集群

        --replicas 1 表示 自动为每一个master节点分配一个slave节点 上面有6个节点,程序会按照一定规则生成 3个master(主)3个slave(从)

[root@localhost src]# redis-cli --cluster create 192.168.142.128:7111 192.168.142.128:7112 192.168.142.128:7113 192.168.142.130:7114 192.168.142.130:7115 192.168.142.130:7116 --cluster-replicas 1  
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.142.130:7115 to 192.168.142.128:7111
Adding replica 192.168.142.128:7113 to 192.168.142.130:7114
Adding replica 192.168.142.130:7116 to 192.168.142.128:7112
M: dc987ed6c56f893ddfd672eea0922366bd7c1a27 192.168.142.128:7111
   slots:[0-5460] (5461 slots) master
M: aaf246b5d43eeecf5b67edc3af8ee39a42b8b238 192.168.142.128:7112
   slots:[10923-16383] (5461 slots) master
S: fe89056b055696d1c9e92d8ee357bdb29cae677b 192.168.142.128:7113
   replicates c7630d84af8e780fb8940b98d7233fadd9ac92fe
M: c7630d84af8e780fb8940b98d7233fadd9ac92fe 192.168.142.130:7114
   slots:[5461-10922] (5462 slots) master
S: ac2f315b6bbcbbaba2d9b3941db80094ccb8d580 192.168.142.130:7115
   replicates dc987ed6c56f893ddfd672eea0922366bd7c1a27
S: 8590357fdbde22820c7be24a9b2d816be9255461 192.168.142.130:7116
   replicates aaf246b5d43eeecf5b67edc3af8ee39a42b8b238
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 192.168.142.128:7111)
M: dc987ed6c56f893ddfd672eea0922366bd7c1a27 192.168.142.128:7111
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: fe89056b055696d1c9e92d8ee357bdb29cae677b 192.168.142.128:7113
   slots: (0 slots) slave
   replicates c7630d84af8e780fb8940b98d7233fadd9ac92fe
M: aaf246b5d43eeecf5b67edc3af8ee39a42b8b238 192.168.142.128:7112
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: ac2f315b6bbcbbaba2d9b3941db80094ccb8d580 192.168.142.130:7115
   slots: (0 slots) slave
   replicates dc987ed6c56f893ddfd672eea0922366bd7c1a27
M: c7630d84af8e780fb8940b98d7233fadd9ac92fe 192.168.142.130:7114
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 8590357fdbde22820c7be24a9b2d816be9255461 192.168.142.130:7116
   slots: (0 slots) slave
   replicates aaf246b5d43eeecf5b67edc3af8ee39a42b8b238
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@localhost src]#

        冷暖自知一抹茶ck

        至此,集群搭建完毕。


        四、客户端连接集群,集群测试

[root@localhost src]# ./redis-cli -c -h 192.168.142.130 -p 7114       #启动集群客户端  
192.168.142.130:7114> cluster info                         #查看集群信息
cluster_state:ok                                                      #集群状态
cluster_slots_assigned:16384                             #槽分配
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:4
cluster_stats_messages_ping_sent:268
cluster_stats_messages_pong_sent:269
cluster_stats_messages_meet_sent:1
cluster_stats_messages_sent:538
cluster_stats_messages_ping_received:265
cluster_stats_messages_pong_received:269
cluster_stats_messages_meet_received:4
cluster_stats_messages_received:538
192.168.142.130:7114> 
192.168.142.130:7114> cluster nodes                       #查看节点信息(Master/Slaver之间的关系)
fdd21d8a6b3d96681bd50374edaa8246f488c7db 192.168.142.130:7116@17116 slave 65d4cebd0a8f80e8913778e5099e66f673c1d06e 0 1555855669000 6 connected
bcb9496bc314153c8de8b1de1c55674d7a9a2e5f 192.168.142.128:7111@17111 master - 0 1555855669000 1 connected 0-5460
75054a3e914b7a2ad7d85d4579410098482b8cc3 192.168.142.128:7113@17113 slave 0960860c8bdf7dcbdbf170cf9aa215119900c73b 0 1555855670000 4 connected
0960860c8bdf7dcbdbf170cf9aa215119900c73b 192.168.142.130:7114@17114 myself,master - 0 1555855669000 4 connected 5461-10922
14325f7bcb350da87436d6ed57d57b5906a7fb49 192.168.142.130:7115@17115 slave bcb9496bc314153c8de8b1de1c55674d7a9a2e5f 0 1555855670599 5 connected
65d4cebd0a8f80e8913778e5099e66f673c1d06e 192.168.142.128:7112@17112 master - 0 1555855668581 2 connected 10923-16383
192.168.142.130:7114> 



###检查集群状态,打印如下,发现redis-cluster自动给节点分配了主从属性,但是6个节点却有四个主节点,导致两个主节点没slave.
###这样的集群其实是创建失败的,需要删除集群重新创建。
[root@localhost src]# redis-cli --cluster check 192.168.142.130:7114             #检查集群状态
192.168.142.128:7111 (11bf02d1...) -> 0 keys | 5461 slots | 1 slaves.
192.168.142.128:7113 (a4760e67...) -> 0 keys | 5462 slots | 1 slaves.
192.168.142.128:7112 (11092454...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.142.130:7114)
S: 280cfb7c3630359c282d14b26a3a95c07d48f139 192.168.142.130:7114
   slots: (0 slots) slave
   replicates a4760e67d20aab7b46b8c6f943fd6a6285bd470a
M: 11bf02d17a597268e1ec4b3c3360bca939ccf88f 192.168.142.128:7111
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: a4760e67d20aab7b46b8c6f943fd6a6285bd470a 192.168.142.128:7113
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 2d0548abf959fb66be35bf727ef70afbe8745d0d 192.168.142.130:7115
   slots: (0 slots) slave
   replicates 11bf02d17a597268e1ec4b3c3360bca939ccf88f
S: 408655310ad91fd3cf203d31f1e5d3092a5d9e00 192.168.142.130:7116
   slots: (0 slots) slave
   replicates 11092454e31f04bc78a220c06fe983a24cd94d1d
M: 11092454e31f04bc78a220c06fe983a24cd94d1d 192.168.142.128:7112
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.


测试:

[root@localhost src]# ./redis-cli -c -h 192.168.142.130 -p 7114
192.168.142.130:7114> set jiqun  frist                    #设置键值    
OK
192.168.142.130:7114> set name ck
OK
192.168.142.130:7114> set age 20                       #age这个键被分配到第1个Master,在插槽741中
-> Redirected to slot [741] located at 192.168.142.128:7111
OK
192.168.142.128:7111> get age
"20"
192.168.142.128:7111>

        可以看到,客户端连接加-c选项的时候,存储和提取key的时候不断在7114和7111之间跳转,这个称为客户端重定向。之所以发生客户端重定向,是因为Redis Cluster中的每个Master节点都会负责一部分的槽(slot),存取的时候都会进行键值空间计算定位key映射在哪个槽(slot)上,如果映射的槽(slot)正好是当前Master节点负责则直接存取,否则就跳转到其他Master节点负的槽(slot)中存取,这个过程对客户端是透明的。


5、redis 集群分区原理

        5.1 槽(slot)的基本概念        

        从上面集群的简单操作中,我们已经知道redis存取key的时候,都要定位相应的槽(slot)。

        Redis 集群键分布算法使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 它们的编号为0、1、2、3……16382、16383,这个槽是一个逻辑意义上的槽,实际上并不存在。redis中的每个key都属于这 16384 个哈希槽的其中一个,存取key时都要进行key->slot的映射计算。

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.25.64:6383 to 192.168.25.64:6380
Adding replica 192.168.25.64:6384 to 192.168.25.64:6381
Adding replica 192.168.25.64:6385 to 192.168.25.64:6382

# 从上面信息可以看出,创建集群的时候,哈希槽被分配到了三个主节点上,从节点是没有哈希槽的,6380 负责编号为 0 - 5460,
共 5461个slots 、6381 负责编号为 5461 - 10922 ,共5462个slots、6382负责编号为 10923 - 16383 共5461个slots

        从上面信息可以看出,创建集群的时候,哈希槽被分配到了三个主节点上,从节点是没有哈希槽的

        5.2 集群分区好处:

        redis的集群分区,最主要的目的都是在移除、添加一个节点时对已经存在的缓存数据的定位影响尽可能的降到最小。redis将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点, 比如说:

        1)、如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 就可以了。

        2)、与此类似, 如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 就可以了。

        因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在 节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线,从而保证集群的可用性。下面我们就来学习下集群中节点的增加和删除。

        新增节点

[root@localhost ~]# cd /usr/local/src/redis-5.0.3/
[root@localhost ~]# cp redis.conf ./cluster7117_redis.conf
[root@localhost ~]# cp redis.conf ./cluster7118_redis.conf

        启动新增加的节点

[root@localhost ~]# cd /usr/local/src/redis-5.0.3/src/
            
[root@localhost src]# redis-server ../cluster7117_redis.conf 
[root@localhost src]# redis-server ../cluster7118_redis.conf

        添加节点到集群

格式:
redis-cli --cluster add-node {新节点IP}:{新节点端口} {任意集群节点IP}:{对应端口} 
#如果添加集群中的主节点,则新添加的就是主节点,如果是从节点则是从节点

[root@localhost src]# ./redis-cli --cluster add-node 192.168.25.64:6386 192.168.25.64:7117
[root@localhost src]# ./redis-cli --cluster add-node 192.168.25.64:6386 192.168.25.64:7118

        删除节点

[root@localhost src]# ./redis-cli --cluster del-node 192.168.142.130:7116 fdd21d8a6b3d96681bd50374edaa8246f488c7db

        查看集群信息

[root@localhost src]# ./redis-cli -c -h 192.168.142.130 -p 7117
192.168.142.130:7114> cluster nodes 


或者用这样可以查看集群检查集群
./redis-cli --cluster check 192.168.142.130:7111

        平衡各节点槽数量

[root@localhost 8005]# redis-cli --cluster rebalance --cluster-threshold 1 127.0.0.1:8000


        自定义分配槽

        从添加主节点输出信息和查看集群信息中可以看出,我们已经成功的向集群中添加了一个主节点,但是这个主节还没有成为真正的主节点,因为还没有分配槽(slot),也没有从节点,现在要给它分配槽(slot)

./redis-cli --cluster reshard 192.168.142.130:7111

        冷暖自知一抹茶ck

#系统提示要移动多少个配槽(slot),并且配槽(slot)要移动到哪个节点,任意输入一个数,如1024,再输入新增节点的ID1ee802b80517
61fd26ab688ff9dca95df35ef3c4

#然后提示要从哪几个节点中移除1024个槽(slot),这里输入‘all’表示从所有的主节点中随机转移,凑够1024个哈希槽,然后就开始从
新分配槽(slot)了。从新分配完后再次查看集群节点信息

        冷暖自知一抹茶ck




        总结:

        1.集群中各台机器的配置信息一致,Master/Slaver关系是在创建集群时由系统分配;

        2.redis集群公用16384个slot,分配给不同的Master;

        3.每个key最终都会位于某一个slot,读取key时会先转向到某一个slot,然后读取其中的值;

        4.新增集群或减少集群(如新增或减少Master)会重新分配slot;

        5.集群的Master/Slaver不知道怎么做容灾,自动切换等,等待进一步研究;



五、redis架构

        冷暖自知一抹茶ck

        1)、架构细节:

        (1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽;
        (2)节点的fail是通过集群中超过半数的节点检测失效时才生效;
        (3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可;
        (4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value;


        2)、 redis-cluster选举:容错

        冷暖自知一抹茶ck

        (1)领着选举过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.
        (2):什么时候整个集群不可用(cluster_state:fail)?
       a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完整时进入fail状态.
       b:如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态.当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误。


        3)、 集群的优点

        优点:

                在master节点下线后,slave节点会自动升为 master 节点,保持集群持续提供服务;

                fail 节点恢复后,会自动添加到集群中,变成slave 节点;

        缺点:

                由于redis 的复制使用异步复制,在自动故障转移的过程中,集群可能会丢失写命令,然而redis几乎是同步执行(将命令回复给客户端,以及将命令复制到slave节点)这两个操作,所以实际中,命令丢失的窗口非常小。


六、数据分区方案

        数据分区有顺序分区、哈希分区等,其中哈希分区由于其天然的随机性,使用广泛;集群的分区方案便是哈希分区的一种。

        哈希分区的基本思路是:对数据的特征值(如 key)进行哈希,然后根据哈希值决定数据落在哪个节点。

        常见的哈希分区包括:哈希取余分区、一致性哈希分区、带虚拟节点的一致性哈希分区等。

        衡量数据分区方法好坏的标准有很多,其中比较重要的两个因素是:

                1)、数据分布是否均匀。

                2)、增加或删减节点对数据分布的影响。

        由于哈希的随机性,哈希分区基本可以保证数据分布均匀;因此在比较哈希分区方案时,重点要看增减节点对数据分布的影响。


        哈希取余分区

        哈希取余分区思路非常简单:计算 key 的 hash 值,然后对节点数量进行取余,从而决定数据映射到哪个节点上。

        该方案最大的问题是,当新增或删减节点时,节点数量发生变化,系统中所有的数据都需要重新计算映射关系,引发大规模数据迁移。


        一致性哈希分区

        一致性哈希算法将整个哈希值空间组织成一个虚拟的圆环,如下图所示,范围为 0-2^32-1。

        

冷暖自知一抹茶ck

        对于每个数据,根据 key 计算 hash 值,确定数据在环上的位置,然后从此位置沿环顺时针行走,找到的第一台服务器就是其应该映射到的服务器。

        与哈希取余分区相比,一致性哈希分区将增减节点的影响限制在相邻节点。

        以上图为例,如果在 node1 和 node2 之间增加 node5,则只有 node2 中的一部分数据会迁移到 node5;如果去掉 node2,则原 node2 中的数据只会迁移到 node4 中,只有 node4 会受影响。

        一致性哈希分区的主要问题在于,当节点数量较少时,增加或删减节点,对单个节点的影响可能很大,造成数据的严重不平衡。

        还是以上图为例,如果去掉 node2,node4 中的数据由总数据的 1/4 左右变为 1/2 左右,与其他节点相比负载过高。


        带虚拟节点的一致性哈希分区

        该方案在一致性哈希分区的基础上,引入了虚拟节点的概念。Redis 集群使用的便是该方案,其中的虚拟节点称为槽(slot)。

        槽是介于数据和实际节点之间的虚拟概念;每个实际节点包含一定数量的槽,每个槽包含哈希值在一定范围内的数据。

        引入槽以后,数据的映射关系由数据 hash->实际节点,变成了数据 hash->槽->实际节点。

        在使用了槽的一致性哈希分区中,槽是数据管理和迁移的基本单位。槽解耦了数据和实际节点之间的关系,增加或删除节点对系统的影响很小。

        仍以上图为例,系统中有 4 个实际节点,假设为其分配 16 个槽(0-15);槽 0-3 位于 node1,4-7 位于 node2,以此类推。

        如果此时删除 node2,只需要将槽 4-7 重新分配即可,例如槽 4-5 分配给 node1,槽 6 分配给 node3,槽 7 分配给 node4;可以看出删除 node2 后,数据在其他节点的分布仍然较为均衡。

        槽的数量一般远小于 2^32,远大于实际节点的数量;在 Redis 集群中,槽的数量为 16384。

        

冷暖自知一抹茶ck

        上面这张图很好的总结了 Redis 集群将数据映射到实际节点的过程:

        Redis 对数据的特征值(一般是key)计算哈希值,使用的算法是 CRC16。

        根据哈希值,计算数据属于哪个槽。

        根据槽与节点的映射关系,计算数据属于哪个节点。





、参考资料

        1.http://blog.csdn.net/zhu_tianwei/article/details/44928779

        2.http://blog.csdn.net/zhu_tianwei/article/details/45009647

        3.http://5i.io/redis-3-0-cluster-configuration/

        4.redis安装3.0版本:https://blog.csdn.net/qq_42815754/article/details/82912130 

        5.redis 5.0.3 讲解、集群搭建: https://www.cnblogs.com/zy-303/p/10273167.htm


常见问题1:

冷暖自知一抹茶ck

删除生成的配置文件nodes.conf,如果不行则说明现在创建的结点包括了旧集群的结点信息,需要删除redis的持久化文件后再重启redis,比如:appendonly.aof、dump.rdb。

cluster-config-file /var/run/nodes-7111.conf        #文件定义位置

再次执行命令,成功创建cluster,
[root@localhost src]# ./redis-cli --cluster create 192.168.142.128:7111 192.168.142.128:7112 192.168.142.128:7113 192.168.142.130:7114 192.168.142.130:7115 192.168.142.130:7116 --cluster-replicas 1

常见问题2:[ERR] Not all 16384 slots are covered by nodes.

执行redis-cli --cluster fix,显示了修正结果,槽位重新分配。

可以执行redis-cli --cluster check host:port检查集群状态slots详细分配。




常用命令:

netstat -tnlp | grep redis #可以看到redis监听端口


redis-cli -c -p port     集群客户端命令

集群
cluster info :打印集群的信息
cluster nodes :列出集群当前已知的所有节点( node),以及这些节点的相关信息。
节点
cluster meet <ip> <port> :将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
cluster forget <node_id> :从集群中移除 node_id 指定的节点。
cluster replicate <node_id> :将当前节点设置为 node_id 指定的节点的从节点。
cluster saveconfig :将节点的配置文件保存到硬盘里面。
槽(slot)
cluster addslots <slot> [slot ...] :将一个或多个槽( slot)指派( assign)给当前节点。
cluster delslots <slot> [slot ...] :移除一个或多个槽对当前节点的指派。
cluster flushslots :移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
cluster setslot <slot> node <node_id> :将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
cluster setslot <slot> migrating <node_id> :将本节点的槽 slot 迁移到 node_id 指定的节点中。
cluster setslot <slot> importing <node_id> :从 node_id 指定的节点中导入槽 slot 到本节点。
cluster setslot <slot> stable :取消对槽 slot 的导入( import)或者迁移( migrate)。
键
cluster keyslot <key> :计算键 key 应该被放置在哪个槽上。
cluster countkeysinslot <slot> :返回槽 slot 目前包含的键值对数量。
cluster getkeysinslot <slot> <count> :返回 count 个 slot 槽中的键  
//新增
CLUSTER SLAVES node-id 返回一个master节点的slaves 列表


冷暖自知一抹茶ck
请先登录后发表评论
  • 最新评论
  • 总共0条评论