Redis- 集群:AKF拆分(y轴和z轴),CAP,主从复制,哨兵机制

  • 容量问题
  • Y轴拆分
  • Z轴拆分
    • 拆分逻辑在Client
    • 拆分逻辑在Proxy
      • 拆分逻辑在Client弊端
      • Proxy拆分逻辑原理
    • redis自带的拆分:cluster
  • twemproxy操作演示
    • 安装:
    • nutcracker.yml 详解
    • 演示
  • predixy操作演示
  • cluster操作演示

容量问题

单机redis在使用的时候会碰到三个问题:单点故障、容量不足、访问压力。

因此我们可以对redis进行AKF拆分,站在x轴的角度上可以对redis进行 主从复制 + 哨兵机制。

主从复制:slave做master的全量备份保证数据的可靠性。master对外提供读写,slave对外提供读操作(读写分离),解决了 部分访问压力。
哨兵机制:对master做高可用,使用 哨兵集群 监控master健康状态,哨兵之间相互通信,如果发现master挂了会进行投票选举 其中一个个slave作为新的master。解决了单点故障的问题。

但是由于slave是master的全量数据,在容量这个维度上来说,redis依然是一个单实例的。对于臃肿的redis实例来说,还需要对其进行y轴个z轴的拆分。

什么是容量问题呢?
如果一个redis,它的内存是有限的,即便服务器有128G内存,也不可能让一个redis实例把128G内存全部使用,因为做持久化等等消耗时间成本很大。所以我们尽量控制一个redis实例只使用几G内存,这样这个实例的所有环节和动作都会很轻盈。

Y轴拆分

在数据可以分类,较比不是很多的情况下,我们可以在Client端把要写入redis数据 根据业务(商品、购物车、订单) 在AKF的Y轴上进行分类,把不同的分类写入不同的redis实例。
换个角度讲,就是每个redis实例自己是不知道拆分的,是Client中融入一部分 业务拆分逻辑 代码,使Client根据不同的业务访问不同的redis。

但是如果根据业务进行拆分后,某一个业务的数据数据量很大(比如:订单),应该如何继续拆分?
答案:在AKF的Z轴上继续拆分。

Z轴拆分

拆分逻辑在Client

Y轴拆分后某一业务的数据量还是很大,我们可以对Z轴方向上,在Client端根据 算法 继续拆分。(sharding 分片)

1. modula(hsah + 取模):

这种方式是在Client增加算法逻辑,把要存入数据的进行 % 运算,后边有几个redis实例,就和几进行 % 运算,根据取模的值,把数据存入到不同的redis实例。

优点: 简单,容易操作。
缺点: 取模 的值是固定的,影响分布式下的扩展性,如果添加新的redis实例会使 模数值 发生改变,再取数据的时候根据 模数 去取就无法查找到数据了。

2. random:


Client把数据随机放到不同的redis实例中:
一定会有很多人会问 ,随机把数据放入不同的redis,取出成本会不会很高?或者根本找不到数据?
但是为什么还会有这random模型呢? 如果存入的是一个list类型(lpush),key为ooxx,那么就会在两个redis中都生成ooxx的key,这个时候 消费者 并不是执行lpush的Client,而是执行rpop的另一个Client,都会从ooxx中取数据,无论从哪个redis取,都会取到key为ooxx的数据。这样就形成了一个类似于消息队列的功能。

说的简单一些,就是应用list类型 左进右出 或者 右进左出 的特性模拟队列,只不过在random模型中Client把list数据分发给不同的redis可以起到一个缓冲的效果,更适合高并发的场景。

3. ketama(一致性hash):

相较于 hash + 取模 的方式 弊端,有一种更好的解决方案,就是ketama的方式,其核心就是 一致性hash 算法。

先了解 一致性hash 算法:


在得到一个长度随机的字符串后(redis的key),经过算法得到一个等宽的其他的值(算法:hash、crc16、crc32、fnv、md5),这个值会和字符串做一个映射。和hash取模算法不同的是,一致性hash没有取模的过程(即:不会影响分布式扩展性),并且要求key和node都要参与计算。
然后会在内存中虚拟出一个环形(哈希环)。


假如这个哈希环由0 — 2^32个数字组成,每一个数字都是一个点。无论后面有多少个redis实例,或新增,或减少,都会给这些redis实例一个ID号(或者IP+Port之类的)唯一标识。

如果这个时候有一个 node1 节点,把node1的ID 经过 一个统一的hash算法就会得到一个值,这个值会映射到哈希环的某一个点上。这个时候新增node2节点,同样把node2节点的ID经过 统一的hash运算 得到一个值,也映射到这个哈希环上某个点。(node在哈希环上对应的点 称之为 物理点)

现在 在哈希环上有两个node映射的物理点,把这两个物理点放入带有排序功能的TreeMap集合里。这个时候如果Client要写入数据,可以把数据的key也参与hash运算后会到一个值,并且这个值同样映射到 哈希环 上点,然后用这个映射点和TreeMap里面的物理点进行对比,查找大过自己并且距离自己最近的点是哪个?最后把数据存入距离自己最近的物理点对应的node就可以了。

优点:
没有固定node数量的限制,不会造成全局洗牌。

缺点:
新增节点后,造成一小部分数据无法命中。
如上图,新增一个节点 node3,把node3的ID进行hash运算得到一个数值,这个数值对应 哈希环 的点 恰好在之前数据映射的点和它存入node之间(data -> node2 变为 data -> node3 -> node2), 此时如果查询data,不会从node2查询,而是会从node3里面查找data,因此查询结果为null。
所以,这种方式只适合做缓存而不适合做数据库,缓存大多为期限,即使node2里面data数据永远不会被查询到,data也会随着时间的推移而被清除掉,或者开启缓存清理策略LRU、LFU。并且node3里面无法查询到数据,可以走数据库从新缓存到node3(缓存击穿),也可以修改为从比自己大的两个node中查找数据。


扩展:虚拟节点
如果node1和node2映射在 哈希环 的点分别在最左边 和 最右边,把哈希环切分成了 上半环 和 下半环,在添加数据的时候就可能出现 数据集中在某个半环上而导致 数据量 的倾斜。
我们可以每个node ID后面依次拼10个数字,让一个ID变成10个,用这些ID做hash运算映射到 哈希环 不同的点上,如果是两个设备在 哈希环 上面就会有20个点,这样做的目的是让一个物理设备出现在 多个 点上,就可以间接的解决数据倾斜的问题。

拆分逻辑在Proxy

拆分逻辑在Client弊端


在Client里实现 Z轴 拆分逻辑,虽然能解决容量问题,但是在实际场景中,一台redis可能要面对多个Client,换言之 每个Client都要和每个redis实例进行连接,况且每个Client不可能只和redis开一个连接,而是应该开一个连接池缓存10个或更多的连接。即便是没有连接池,每次TCP握手和分手都是一个损耗的事情。

结论:redis的连接成本很高。

如何解决?增加proxy代理。

Proxy拆分逻辑原理


可以在Client和redis之间增加一个代理层(proxy),类似于Nginx这种应用层 的反向代理,基于反向代理的基础上 负载均衡服务器。

Client只需要和proxy建立握手,proxy再单独和多个redis实例建立握手,这样就可以减少对redis的socket连接的压力。这个时候我们更关注的是proxy的性能。
基于proxy的理论,可以把在Client的拆分逻辑 迁移 到 代理层,所以在代理层可以对modula、random、ketama进行逻辑实现。

注意:无论拆分逻辑在Client还是Proxy,都没有脱离modula、random、ketama三种模式,并且都只适合作为缓存,不适合做数据库。这个问题如何解决?redis自带的拆分:cluster。

常用的代理:twemproxypredixy

拓展 -> proxy是不需要记录Client状态,本身不存在数据库存储,所以proxy是无状态的 ,很容易的就可以把proxy一变多:
如果在高并发场景下,一个proxy不够用了怎么办:


那就使用两个proxy,让固定Client组连接固定的proxy,为了提高可用性,可以搭建LVS四层 负载均衡 服务器 对两个proxy做负载均衡。
但是LVS也是一个单点,并且不能对后端的proxy集群做健康检查,所以可以使用keepalived建立VIP对LVS做主备HA高可用。

同时建立LVS的VIP也有一个好处:无论企业后端技术多复杂,对用户都是透明的。用户只需要访问VIP就OK!

redis自带的拆分:cluster

redis作为数据库的情况下,可以使用redis自带的拆分cluster。规避了ketama新增redis实例时截断数据的情况,那么cluster是如何做到的呢?

引导:


假如现在有两台redis服务器,分别是redis1和redis2,以后还会出现第三台服务器redis3。
在加入新节点到集群的话,无论拆分逻辑是在Client还是在Proxy,对算法都是一个极大的挑战。

要解决这个问题,可以在 拆分逻辑中 进行 预分区
现在有两个redis节点,未来就可能有10个节点。那么在两个节点的时候,就可以直接取模10个节点,取模的结果为 0 ~ 9 ,两个节点可以分别对0~9个节点做一个mapping(10个槽位),比如:
redis1映射0,1,2,3,4
redis2映射5,6,7,8,9
(各领取5个槽位)。
这个时候如果redis3加入集群,会让redis1和redis2让出几个槽位,比如从redis1中拿到了3和4,在redis2中拿到了8和9(如上图)。移动数据的时候,不需要把redis全部rehash,只需要把3,4,8,9槽位的时点数据找到直接传输给redis3,redis3接收完数据后,会根据 时点数据 跟redis1和redis2传输期间内的数据做一个追平更新,追平的一刹那,再往3,4,8,9槽位存数据就会直接存入redis3。
Client只需要知道映射关系,就可以根据槽位正确的读取数据了。

cluster:


有3台redis服务器,分别是redis1,redis2,redis3。

Client想要存入k1,会随机访问redis1和redis2。
和之前不同的是每一个redis中都存在hash算法,并且保存了集群内其他redis实例的槽位映射关系(知道别人有什么),满足了这两个条件后,就可以让每个redis实例都能当家做主。
这样k1随机进入一个redis实例后(假设这个实例是redis2),redis2会先拿k1进行hash取模算出槽位,用计算的槽位和自己的mapping映射的槽位做一个匹配,如果和自己匹配就直接存入redis2,如果不匹配再和redis2内保存的其他实例的槽位映射关系进行匹配,就能找到k1需要存的redis实例是哪个,把k1返回给Client 并 重定向到正确的redis实例中(假设匹配结果为redis3)。redis3拿到k1后同样要进行hash运算并且 把结果和自身映射槽位进行匹配,匹配成功直接存入自己这个实例当中。

摘要redis中文网:
“实际redis中,Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念。
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽。”

这就是redis自带的cluster,是一种无主模型。

注意:只要把数据拆分,无论逻辑在Client、Proxy、还是redis自身,都会有一个问题 : 聚合操作很难实现。

  1. 一个操作需要几个key,但是这些key都不在一个节点上。
  2. 事务
  3. set集合的交集,并集,差集运算。两个set分别在不同的redis中,如果redis自身实现就会涉及数据移动过程,redis在设计的思想是 计算 向 数据移动,而不是移动数据。redis的特点就是快,所以作者做了一个取舍。

解决方案:问题的起点在于 数据被分开。换言之,数据不会被分开就能够实现 聚合操作。
操作的key都在相同的节点,可以用 hash tag 。
比如:把key设置成为{oo}k1,{oo}k2,{oo}k3这种带有{}内部有固定标识的 格式,这样在存入key的时候会使用 oo 进行取模,而不会使用k1,k2,k3进行取模。进而存入同一个redis节点。

twemproxy操作演示

GitHub地址:https://github.com/twitter/twemproxy

安装:

cd /soft/twemproxy                                       //新建存放twemproxy的目录
git clone  https://github.com/twitter/twemproxy.git     //从git上clone下该项目
yum install automake libtool  -y                        //安装automake和libtool
autoreconf -fvi                                         //执行完之后目录文件多出configure可执行文件
./configure                                             //执行configure文件
make                                                    //进行编译
cd src/                                                 //进入src目录,会看到nutcracker可执行程序
cd ../                                                  //会看见有scripts脚本目录
cd scripts                                              //进入scripts目录,会看见nutcracker.init文件###################################  把twemproxy变为服务  ##################################cp nutcracker.init /etc/init.d/twemproxy                    //把nutcracker.init拷贝到/etc/init.d/目录
cd /etc/init.d/                                             //发现cp后的twemproxy还没有变绿,所以要赋予权限
chmod 777 twemproxy                                         //赋予权限,使其变绿
vi twemproxy                            //发现里面OPTIONS="-d -c /etc/nutcracker/nutcracker.yml" 需要在指定目录有nutcracker.yml文件。
mkdir  /etc/nutcracker                                      //创建目录
cd /soft/twemproxy/twemproxy/conf               //回到twemproxy安装目录下的conf目录,里面有nutcracker.yml文件
cp ./*  /etc/nutcracker/                                    //拷贝当前目录下所有文件到 /etc/nutcracker/ 目录
cd  /soft/twemproxy/twemproxy/src                           //进入src目录下
cp nutcracker /usr/bin/                                     //把之前编译的可执行程序复制到 /usr/bin/  目录
cd /etc/nutcracker/                                         //进入之前移动配置文件的目录
cp nutcracker.yml nutcracker.yml.bak                        //把nutcracker.yml文件进行备份(好习惯)
vi nutcracker.yml                                               //修改配置文件,下面有详细介绍

nutcracker.yml 详解

alpha:listen: 127.0.0.1:22121            #代理众多redis实例对外暴露的统一访问接口hash: fnv1a_64                   #使用的hash算法distribution: ketama              #分布式使用的模型auto_eject_hosts: trueredis: true                      #代理的是redisserver_retry_timeout: 2000server_failure_limit: 1servers:- 127.0.0.1:6379:1- 127.0.0.1:6380:1             #计量代理的两个redis实例

演示

先启动两个redis:

cd
mkdir data
cd data
mkdir 6379
mkdir 6380
cd 6379
redis-server --port 6379############# 切入到新窗口cd data/6380
redis-server --port 6380

启动twemproxy :

[root@z8524210 6379]# service twemproxy start
Reloading systemd:                                         [  确定  ]
Starting twemproxy (via systemctl):                        [  确定  ]
[root@z8524210 6379]#

启动后,连接twemproxy提供的统一接口,并添加元素:

[root@z8524210 6379]# redis-cli -p 22121
127.0.0.1:22121> set k1 aaa
OK
127.0.0.1:22121> set k2 asd
OK                                                  //在统一接口里添加4个元素 k1,k2,k3和 1
127.0.0.1:22121> set k3 asd
OK                                                  //这些数据都存到哪些实例了呢?
127.0.0.1:22121> set 1 zhangsan
OK
127.0.0.1:22121>

然后连接redis6379和redis6380接口,并查看各自实例的元素:

#######################################  6379  ####################################[root@z8524210 ~]# redis-cli -p 6379
127.0.0.1:6379> KEYS *
1) "1"                                                //6379里面有一个 1 元素
127.0.0.1:6379> #######################################  6380  ####################################[root@z8524210 ~]# redis-cli -p 6380
127.0.0.1:6380> KEYS *
1) "k1"
2) "k3"                                               //6380里面有 k1,k2,k3三个元素
3) "k2"
127.0.0.1:6380>

但是因为数据分治,所以不支持聚合操作:

127.0.0.1:22121> KEYS *
Error: Server closed the connection                 //聚合操作会报错
127.0.0.1:22121> WATCH k1
Error: Server closed the connection
127.0.0.1:22121> MULTI
Error: Server closed the connection
127.0.0.1:22121>

predixy操作演示

Github地址:https://github.com/joyieldInc/predixy

Predixy可以在所有主流平台下编译,推荐在linux下使用,需要支持C++11的编译器。所以直接下载别人编译好的程序。

[root@z8524210 ~]# mkdir predixy
[root@z8524210 ~]# cd predixy/
[root@z8524210 ~]# wget https://github.com/joyieldInc/predixy/releases/download/1.0.5/predixy-1.0.5-bin-amd64-linux.tar.gz
[root@z8524210 predixy]# cd predixy/               //下载完之后进入predixy目录

下载完之后进入predixy目录:

[root@z8524210 predixy]# ll
总用量 36
drwxr-xr-x. 2 root root   21 6月  11 17:47 bin
drwxr-xr-x. 2 root root  178 6月  11 18:03 conf
-rw-r--r--. 1 root root   26 6月  11 17:42 _config.yml
drwxr-xr-x. 3 root root  112 6月  11 17:42 doc
-rw-r--r--. 1 root root 1537 6月  11 17:42 LICENSE
-rw-r--r--. 1 root root  274 6月  11 17:42 Makefile
-rw-r--r--. 1 root root 5680 6月  11 17:42 README_CN.md
-rw-r--r--. 1 root root 4200 6月  11 17:42 README.md
drwxr-xr-x. 2 root root 4096 6月  11 17:43 src
drwxr-xr-x. 2 root root   39 6月  11 17:42 test/**
*   可以看到有可执行程序的bin目录,里面只有一个predixy可执行程序。
*   还有conf配置文件目录,里面是很多配置文件
*/

进入到conf目录:

[root@z8524210 predixy]# cd conf/
[root@z8524210 conf]# ll
总用量 36
-rw-r--r--. 1 root root 2395 6月  11 17:42 auth.conf
-rw-r--r--. 1 root root 1041 6月  11 17:42 cluster.conf              //cluster配置文件
-rw-r--r--. 1 root root 3426 6月  11 17:42 command.conf
-rw-r--r--. 1 root root  781 6月  11 17:42 dc.conf
-rw-r--r--. 1 root root 2121 6月  11 17:42 latency.conf
-rw-r--r--. 1 root root 2544 6月  11 17:56 predixy.conf              //主配置文件
-rw-r--r--. 1 root root 1849 6月  11 18:03 sentinel.conf         //哨兵配置文件
-rw-r--r--. 1 root root 2016 6月  11 17:42 standalone.conf
-rw-r--r--. 1 root root   98 6月  11 17:42 try.conf
[root@z8524210 conf]#

vi predixy.conf,需要设置的地方主要有两个:

GENERAL模块:Bind 127.0.0.1:7617             //设置对外暴露的统一接口
SERVERS模块:Include sentinel.conf              //引入哨兵配置文件

设置好predixy.conf文件后,继续修改哨兵的配置文件vi sentinel.conf:

SentinelServerPool {Databases 16Hash crc16HashTag "{}"Distribution modulaMasterReadPriority 60StaticSlaveReadPriority 50DynamicSlaveReadPriority 50RefreshInterval 1ServerTimeout 1ServerFailureLimit 10ServerRetryTimeout 1KeepAlive 120Sentinels {+ 127.0.0.1:26379                             //三个哨兵的 IP+端口+ 127.0.0.1:26380+ 127.0.0.1:26381}Group ooxx {                     //一套哨兵可以监控多套主从,一个Group为一套主从。}                                    //Client写入的数据会被打散分别存入ooxx主从的master和xxoo主从的master。Group xxoo {}
}

编写三个哨兵的配置文件:

[root@z8524210 test]# vi 26379.conf
port 26379
sentinel monitor ooxx 127.0.0.1 36379 2         //第一套主从ooxx的master ID+ Port,组为ooxx
sentinel monitor xxoo 127.0.0.1 46379 2         //第二套主从xxoo的master ID+ Port    组为xxoo

[root@z8524210 test]# vi 26379.conf
port 26380
sentinel monitor ooxx 127.0.0.1 36379 2
sentinel monitor xxoo 127.0.0.1 46379 2

[root@z8524210 test]# vi 26379.conf
port 26381
sentinel monitor ooxx 127.0.0.1 36379 2
sentinel monitor xxoo 127.0.0.1 46379 2

在三个窗口分别启动哨兵:

[root@z8524210 test]# redis-server 26379.conf --sentinel
[root@z8524210 test]# redis-server 26380.conf --sentinel
[root@z8524210 test]# redis-server 26381.conf --sentinel

建立四个个文件夹36379、36380、46379、46380,分别进去启动对应的redis

//开启两个主机
[root@z8524210 36379]# redis-server --port 36379
[root@z8524210 46379]# redis-server --port 46379//开启两个从机,追随对应的主机
[root@z8524210 36380]# redis-server --port 36380 --replicaof 127.0.0.1 36379
[root@z8524210 46380]# redis-server --port 46380 --replicaof 127.0.0.1 46379

启动predixy代理:

[root@z8524210 bin]# ./predixy ../conf/predixy.conf
2020-06-11 19:38:06.154417 N Proxy.cpp:112 predixy listen in 127.0.0.1:7617
2020-06-11 19:38:06.154595 N Proxy.cpp:143 predixy running with Name:PredixyExample Workers:1
2020-06-11 19:38:06.154953 N Handler.cpp:456 h 0 create connection pool for server 127.0.0.1:26380
2020-06-11 19:38:06.155035 N ConnectConnectionPool.cpp:42 h 0 create server connection 127.0.0.1:26380 5
2020-06-11 19:38:06.155150 N Handler.cpp:456 h 0 create connection pool for server 127.0.0.1:26381
2020-06-11 19:38:06.155172 N ConnectConnectionPool.cpp:42 h 0 create server connection 127.0.0.1:26381 6
2020-06-11 19:38:06.155212 N Handler.cpp:456 h 0 create connection pool for server 127.0.0.1:26379
2020-06-11 19:38:06.155225 N ConnectConnectionPool.cpp:42 h 0 create server connection 127.0.0.1:26379 7
2020-06-11 19:38:06.156206 N StandaloneServerPool.cpp:422 sentinel server pool group ooxx create master server 127.0.0.1:36379
2020-06-11 19:38:06.156221 N StandaloneServerPool.cpp:472 sentinel server pool group ooxx create slave server 127.0.0.1:36380
2020-06-11 19:38:06.156226 N StandaloneServerPool.cpp:422 sentinel server pool group xxoo create master server 127.0.0.1:46379
2020-06-11 19:38:06.156228 N StandaloneServerPool.cpp:472 sentinel server pool group xxoo create slave server 127.0.0.1:46380 /**
*   可以从日志中看到,对外暴露了7617的统一访问接口。
*   以及3个哨兵的 IP + Port
*   还有两队主从集群
*/

往7617统一接口中存入key,然后验证存入的key具体存入哪个实例。

/**
*   往7617统一接口中,存入k1和k2和hash tag 的key
*/
[root@z8524210 ~]# redis-cli -p 7617
127.0.0.1:7617> set k1 sdasd
OK
127.0.0.1:7617> get k1
"sdasd"
127.0.0.1:7617> set k2 aaaa
OK
127.0.0.1:7617> set {xx}k1 dasdas
OK
127.0.0.1:7617> set {xx}k2 dasdas
OK
127.0.0.1:7617> set {xx}k3 dasdas
OK

/**
*   连接36379 mastr ,查看数据
*/
[root@z8524210 ~]# redis-cli -p 36379
127.0.0.1:36379> KEYS *
1) "k1"
127.0.0.1:36379> //能够发现k1和k2分别存入了36379和46379两个master中
/**
*   连接46379 mastr ,查看数据,发现hash tag 都存到了这个主机里
*/
[root@z8524210 ~]# redis-cli -p 46379
127.0.0.1:46379> KEYS *
1) "{xx}k2"
2) "k2"
3) "{xx}k3"
4) "{xx}k1"
127.0.0.1:46379>

但是因为分治的原因,不能实现聚合操作,除非配置文件中只有一套主从(单group):

127.0.0.1:7617> WATCH {xx}k1
(error) ERR forbid transaction in current server pool
127.0.0.1:7617>

当ooxx的36379 master挂了后,哨兵会发现,然后36380会成为新的master:

127.0.0.1:7617> set k5 dsd
OK
127.0.0.1:7617>
[root@z8524210 ~]# redis-cli -p 36380
127.0.0.1:36380> KEYS *
1) "k5"
2) "k1"
127.0.0.1:36380>

代理就是解耦 后端的复杂度,使用的时候比较舒适!

cluster操作演示

先去使用测试脚本感受一下:

[root@z8524210 ~]# cd /soft/redis-5.0.4/utils/create-cluster
[root@z8524210 create-cluster]# vi create-cluster      //查看脚本

create-cluster脚本(部分):

#!/bin/bash# Settings
PORT=30000
TIMEOUT=2000
NODES=6                    //表示一共有6个节点
REPLICAS=1             //有三个slave节点

启动6个节点:

[root@z8524210 create-cluster]# ./create-cluster start
Starting 30001
Starting 30002
Starting 30003
Starting 30004
Starting 30005
Starting 30006
[root@z8524210 create-cluster]#

创建cluster集群:

[root@z8524210 create-cluster]# ./create-cluster create
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460                                  //这里显示有三个主,第一个master有0-5460个槽位
Master[1] -> Slots 5461 - 10922                              // 第二个master有5461-10922个槽位
Master[2] -> Slots 10923 - 16383                         // 第三个master有10923-16383个槽位
Adding replica 127.0.0.1:30005 to 127.0.0.1:30001           //123位master,456为slave
Adding replica 127.0.0.1:30006 to 127.0.0.1:30002
Adding replica 127.0.0.1:30004 to 127.0.0.1:30003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 604529304a6ff642659ca98c0772ae97df3ca57e 127.0.0.1:30001slots:[0-5460] (5461 slots) master
M: daf084af642bb6369eb0adb72463eb6c2fdcd240 127.0.0.1:30002slots:[5461-10922] (5462 slots) master
M: e55845c60c3039d776ae7fb4a8c5cb73cf0117da 127.0.0.1:30003slots:[10923-16383] (5461 slots) master
S: c647248988b60acaddd535a57c6e6ddaa4e37728 127.0.0.1:30004replicates 604529304a6ff642659ca98c0772ae97df3ca57e
S: 34e7bc777d6ccf28e5133ff138217ad1282a6db7 127.0.0.1:30005replicates daf084af642bb6369eb0adb72463eb6c2fdcd240
S: bd8d511ce888966443720b1ad453b8c4edc1abc3 127.0.0.1:30006replicates e55845c60c3039d776ae7fb4a8c5cb73cf0117da
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 127.0.0.1:30001)
M: 604529304a6ff642659ca98c0772ae97df3ca57e 127.0.0.1:30001slots:[0-5460] (5461 slots) master1 additional replica(s)
S: bd8d511ce888966443720b1ad453b8c4edc1abc3 127.0.0.1:30006slots: (0 slots) slavereplicates e55845c60c3039d776ae7fb4a8c5cb73cf0117da
S: 34e7bc777d6ccf28e5133ff138217ad1282a6db7 127.0.0.1:30005slots: (0 slots) slavereplicates daf084af642bb6369eb0adb72463eb6c2fdcd240
S: c647248988b60acaddd535a57c6e6ddaa4e37728 127.0.0.1:30004slots: (0 slots) slavereplicates 604529304a6ff642659ca98c0772ae97df3ca57e
M: daf084af642bb6369eb0adb72463eb6c2fdcd240 127.0.0.1:30002slots:[5461-10922] (5462 slots) master1 additional replica(s)
M: e55845c60c3039d776ae7fb4a8c5cb73cf0117da 127.0.0.1:30003slots:[10923-16383] (5461 slots) master1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@z8524210 create-cluster]#

以普通Client存入数据会报错:

[root@z8524210 create-cluster]# redis-cli -p 30001
127.0.0.1:30001> KEYS *
(empty list or set)
127.0.0.1:30001> set k1 dasd
(error) MOVED 12706 127.0.0.1:30003         //报错,提示要移动到30003上才能创建,应该用cluster的方式进入客户端
127.0.0.1:30001>

用cluster的方式进入Client:

[root@z8524210 create-cluster]# redis-cli -c -p 30001
127.0.0.1:30001> set k1 aaaa
-> Redirected to slot [12706] located at 127.0.0.1:30003     //存入k1的时候会跳转到30003客户端
OK
127.0.0.1:30003> set k2 cccc
-> Redirected to slot [449] located at 127.0.0.1:30001           //存入k2的时候会跳转到30001客户端
OK
127.0.0.1:30001> set k3 cccc                                 //k3计算后,就在30001客户端,所以没有跳转
OK
127.0.0.1:30001> set {xx}k1 asds
-> Redirected to slot [15983] located at 127.0.0.1:30003     //hash tag的方式可以让key存入同一个节点
OK
127.0.0.1:30003> set {xx}k2 asds
OK
127.0.0.1:30003> set {xx}k3 asds
OK
127.0.0.1:30003> set {xx}k4 asds
OK
127.0.0.1:30003> WATCH k2                                //非hash tag聚合操作会报错
-> Redirected to slot [449] located at 127.0.0.1:30001
OK
127.0.0.1:30001> MULTI
OK
127.0.0.1:30001> get k1
-> Redirected to slot [12706] located at 127.0.0.1:30003
"dasd"
127.0.0.1:30003> set k5 dasd
OK
127.0.0.1:30003> EXEC
(error) ERR EXEC without MULTI                      //报错了
127.0.0.1:30003> WATCH {xx}k1                        //使用hash tag就能实现聚合操作,因为数据都在一个实例里
OK
127.0.0.1:30003> MULTI
OK
127.0.0.1:30003> get {xx}k2
QUEUED
127.0.0.1:30003> get {xx}k3
QUEUED
127.0.0.1:30003> set {xx}k4 dasda
QUEUED
127.0.0.1:30003> exec
1) "asds"
2) "asds"
3) OK
127.0.0.1:30003>

测试脚本的命令:

[root@z8524210 create-cluster]# ./create-cluster satrt              //启动节点
[root@z8524210 create-cluster]# ./create-cluster create            //创建集群
[root@z8524210 create-cluster]# ./create-cluster stop              //停止集群和节点
[root@z8524210 create-cluster]# ./create-cluster clean             //清理数据文件/**
*   在真实环境中,可以把satrt的步骤 换成 依次启动我们自己的集群节点。
*   create启动集群的步骤,可以使用客户端命令启动
*/

真实使用:

先查看帮助命令

[root@z8524210 create-cluster]# redis-cli --cluster help
Cluster Manager Commands:create         host1:port1 ... hostN:portN--cluster-replicas <arg>check          host:port--cluster-search-multiple-ownersinfo           host:portfix            host:port--cluster-search-multiple-ownersreshard        host:port--cluster-from <arg>--cluster-to <arg>--cluster-slots <arg>--cluster-yes--cluster-timeout <arg>--cluster-pipeline <arg>--cluster-replacerebalance      host:port--cluster-weight <node1=w1...nodeN=wN>--cluster-use-empty-masters--cluster-timeout <arg>--cluster-simulate--cluster-pipeline <arg>--cluster-threshold <arg>--cluster-replaceadd-node       new_host:new_port existing_host:existing_port--cluster-slave--cluster-master-id <arg>del-node       host:port node_idcall           host:port command arg arg .. argset-timeout    host:port millisecondsimport         host:port--cluster-from <arg>--cluster-copy--cluster-replacehelp           For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.[root@z8524210 create-cluster]#

模拟启动6个节点:

[root@z8524210 create-cluster]# ./create-cluster start
Starting 30001
Starting 30002
Starting 30003
Starting 30004
Starting 30005
Starting 30006/**
*   手工启动的redis实例需要在配置文件中开启 cluster-enabled yes
*/

使用客户端手工创建集群:

[root@z8524210 create-cluster]# redis-cli --cluster create 127.0.0.1:30001 127.0.0.1:30002 127.0.0.1:30003 127.0.0.1:30004 127.0.0.1:30005 127.0.0.1:30006 --cluster-replicas 1

移动槽位:

[root@z8524210 create-cluster]# redis-cli --cluster reshard 127.0.0.1:30001
>>> Performing Cluster Check (using node 127.0.0.1:30001)
M: 07a92516271c6c748d89f2b8adaace50f3385d46 127.0.0.1:30001                 //30001的IDslots:[2000-5460] (3461 slots) master1 additional replica(s)
S: b1c430bce3b79b4d8959b9b4f575a723f2fce84c 127.0.0.1:30006slots: (0 slots) slavereplicates 2089c5c063fda989cfbbc83171654bcde79a98d9
S: 774dd32475129b76c06c512cd2d1316e507970a3 127.0.0.1:30005slots: (0 slots) slavereplicates 76be6e16cbdd1e489672a3d63de0e4914347ec9d
S: 20c688e9a5151d149c1c052ad801a8fff971ef34 127.0.0.1:30004slots: (0 slots) slavereplicates 07a92516271c6c748d89f2b8adaace50f3385d46
M: 76be6e16cbdd1e489672a3d63de0e4914347ec9d 127.0.0.1:30002                 //30002的IDslots:[0-1999],[5461-10922] (7462 slots) master1 additional replica(s)
M: 2089c5c063fda989cfbbc83171654bcde79a98d9 127.0.0.1:30003                 //30003的IDslots:[10923-16383] (5461 slots) master1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 2000
What is the receiving node ID? 07a92516271c6c748d89f2b8adaace50f3385d46     //这里添加新节点的ID
Please enter all the source node IDs.Type 'all' to use all the nodes as source nodes for the hash slots.      // all表示从所有节点中抽取Type 'done' once you entered all the source nodes IDs.                    //done 表示结束
Source node #1: 76be6e16cbdd1e489672a3d63de0e4914347ec9d                    // 输入30002的ID,表示从30002中移动槽位
Source node #2: done                                                //结束,按回车,开始移动槽位....Do you want to proceed with the proposed reshard plan (yes/no)? yes    //输入yes表示赞同,回车,等待移动完成

查看槽位:

[root@z8524210 create-cluster]# redis-cli --cluster info 127.0.0.1:30001        //随便选一个节点的ip端口
127.0.0.1:30001 (07a92516...) -> 0 keys | 5461 slots | 1 slaves.     //之前30001有7000多槽位,现在变为5000了
127.0.0.1:30002 (76be6e16...) -> 0 keys | 5462 slots | 1 slaves.     //之前30002有3000多槽位,现在变为5000了
127.0.0.1:30003 (2089c5c0...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
[root@z8524210 create-cluster]#

查看节点的详情:

[root@z8524210 create-cluster]# redis-cli --cluster check 127.0.0.1:30001           //随便选一个集群中节点的ip和端口


戏入人生
整理完毕!

8.Redis- 集群:AKF拆分(y轴和z轴),twemproxy,predixy,cluster相关推荐

  1. 手把手搭建一个redis集群

    文章目录 前言 安装的含义 安装redis redis编译安装 redis集群 redis集群的使用 C++工程连接使用redis-cluster hiredis-cluster 总结 前言 所谓&q ...

  2. 惊呆了,竟然可以用这种方式秒建 Redis 集群?

    作者 | 老王 来源 | Java 中文社区 前面我们讲了<Redis 性能优化的 13 条军规!>,其中最重要的一条就是使用 Redis 的集群功能,那么本文我们就来看看,如何用 1s ...

  3. 惊呆了,竟然可以用这种方式秒建Redis集群?

    前面我们讲了<Redis 性能优化的 13 条军规!>,其中最重要的一条就是使用 Redis 的集群功能,那么本文我们就来看看,如何用 1s 钟的时间来创建一个 Redis 集群. Red ...

  4. redis集群方式介绍

    redis单机,redis集群,redis哨兵这三种服务器部署方式对应到spring boot的具体操作就是三个不同的configuration配置类. 单机存在的隐患: ①单点故障 ②容量有限 ③压 ...

  5. Redis集群:一致性哈希

    一.Redis集群的使用 我们在使用Redis的时候,为了保证Redis的高可用,提高Redis的读写性能,最简单的方式我们会做主从复制,组成Master-Master或者Master-Slave的形 ...

  6. redis 集群 实操 (史上最全、5w字长文)

    文章很长,建议收藏起来慢慢读! 总目录 博客园版 为大家准备了更多的好文章!!!! 推荐:尼恩Java面试宝典(持续更新 + 史上最全 + 面试必备)具体详情,请点击此链接 尼恩Java面试宝典,34 ...

  7. 技术分享 | Redis 集群架构解析

    作者:贲绍华 爱可生研发中心工程师,负责项目的需求与维护工作.其他身份:柯基铲屎官. 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源. 一.集群架构的 ...

  8. Linux系统搭建Solr和Redis集群详细步骤

    1 搭建Solr集群(SolrCloud) 1.1 Zookeeper介绍 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoo ...

  9. docker 实现redis集群搭建

    摘要:接触docker以来,似乎养成了一种习惯,安装什么应用软件都想往docker方向做,今天就想来尝试下使用docker搭建redis集群. 首先,我们需要理论知识:Redis Cluster是Re ...

最新文章

  1. python【力扣LeetCode算法题库】面试题62- 圆圈中最后剩下的数字(约瑟夫环)
  2. 量子计算机到底多强大?从量子运算看清楚它们的能力
  3. yum 找不到程序,yum更换国内阿里源
  4. mysql = 索引_深入MySQL索引
  5. GitHub 和 Gitee 树形展示插件
  6. bzoj 4260: Codechef REBXOR(01字典树)
  7. java核心知识点学习----创建线程的第三种方式Callable和Future CompletionService
  8. 娃哈哈的新品,为什么打动不了年轻人?
  9. 使用ffmpeg+opencv播放ts格式的视频
  10. python sql语句换行_python一行sql太长折成多行并且有多个参数的方法
  11. 30分钟扫描一亿行代码库,bug漏洞都能找,这款Facebook神器黑粉都赞叹不已
  12. 聚会活跃气氛小程序-喝酒神器
  13. 小程序CMS(开通预览)
  14. mysql Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) fo...
  15. C语言中c2664错误,【求助贴】c++错误error C2664
  16. 来自卡内基梅隆计算机科学系主任的回复
  17. 【渝粤教育】国家开放大学2019年春季 8简明现代汉语 参考试题
  18. cocos creator 2.3.2火柴人密室逃脱闯关游戏 H5+安卓+IOS三端源码
  19. 卸载流氓透明APP,帮老人清理手机弹窗广告
  20. CycleGAN(六)模型结构更改

热门文章

  1. 台式电脑计算机在哪,给力:如何查看台式机的配置,在哪里查看计算机的配置...
  2. 影视感悟专题---2、《大染坊》
  3. Java项目:酒吧后台管理系统(java+SSM+JSP+HTML+mysql)
  4. 【PyQt】自制的MC披风生成器
  5. 2020美亚个人赛复盘
  6. 永磁直流无刷电机设计之路(一)——概述
  7. android权限设置在哪找,Android权限申请与打开权限设置页面
  8. 证途网可靠吗,我在证途网备考一建之路
  9. Keil C51与STC-ISP安装
  10. NET下基于OO4O,FME,ODP.NET的Oracle Spatial空间数据读取操作