Redis的Cluster

发表时间:2018-03-14 17:03:28 浏览量( 10 ) 留言数( 0 )

学习目标:

1、了解Sentine机制的原理

2、掌握Sentine的搭建


学习过程:

   Redis Cluster是Redis的集群实现,内置数据自动分片机制,集群内部将所有的key映射到16384个Slot中,集群中的每个Redis Instance负责其中的一部分的Slot的读写。集群客户端连接集群中任一Redis Instance即可发送命令,当Redis Instance收到自己不负责的Slot的请求时,会将负责请求Key所在Slot的Redis Instance地址返回给客户端,客户端收到后自动将原请求重新发往这个地址,对外部透明。一个Key到底属于哪个Slot由crc16(key) % 16384 决定

attcontent/a3dd5106-8499-449a-8f57-dcef0a1c66d5.png


    Redis 集群提供了以下两个好处:

  • 将数据自动切分(split)到多个节点的能力。

  • 当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。

    Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。

    集群中的每个节点负责处理一部分哈希槽。 举个例子, 一个集群可以有三个哈希槽, 其中:

    节点 A 负责处理 0 号至 5500 号哈希槽。

    节点 B 负责处理 5501 号至 11000 号哈希槽。

    节点 C 负责处理 11001 号至 16384 号哈希槽。

    这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。 比如说:

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

因    为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线。


Redis 集群中的主从复制

    为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。

    在之前列举的节点 A 、B 、C 的例子中, 如果节点 B 下线了, 那么集群将无法正常运行, 因为集群找不到节点来处理 5501 号至 11000 号的哈希槽。

    另一方面, 假如在创建集群的时候(或者至少在节点 B 下线之前), 我们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理 5501 号至 11000 号的哈希槽, 这样集群就不会因为主节点 B 的下线而无法正常运作了。

   不过如果节点 B 和 B1 都下线的话, Redis 集群还是会停止运作。



二、安装

1、启动redis

[root@run1 etc]# cp redis.conf redis7000.conf

[root@run1 etc]# cp redis.conf redis7001.conf


分别修改对应的端口

redis7000.conf文件修改如下:

port 7000

cluster-enabled yes

cluster-config-file nodes-7000.conf

cluster-node-timeout 15000


redis7001.conf文件修改如下:

port 7001

cluster-enabled yes

cluster-config-file nodes-7001.conf

cluster-node-timeout 15000


然后把这两个配置文件复制到另外两台服务器中。

 scp redis700*.conf root@192.168.8.235:/etc

 scp redis700*.conf root@192.168.8.236:/etc


分别在三台服务器中启动就可以了

root@run1 bin]# ./redis-server /etc/redis7000.conf

[root@run1 bin]# ./redis-server /etc/redis7001.conf

查看是否启动成功

[root@run1 bin]# ps -ef | grep redis

root      1527     1  0 13:58 ?        00:00:00 ./redis-server 127.0.0.1:7000     

root      1531     1  0 13:58 ?        00:00:00 ./redis-server 127.0.0.1:7001  


2、安装集群

先安装 ruby

  yum install ruby rubygems -y


下载redis-3.3.5.gem 并安装

https://rubygems.org/gems/redis/versions/3.3.5

[root@run1 ~]# gem install redis-3.3.5.gem 

Successfully installed redis-3.2.2

1 gem installed

Installing ri documentation for redis-3.2.2...

Installing RDoc documentation for redis-3.2.2...


拷贝 redis-trib.rb 到/opt/redis/bin

[root@run1 bin]# cd ~/redis-3.2.11/src/redis-trib.rb .


执行建立集群命令

[root@run1 bin]# ./redis-trib.rb create --replicas 1 192.168.8.234:7000 192.168.8.234:7001 192.168.8.235:7000 192.168.8.235:7001 192.168.8.236:7000 192.168.8.236:7001


    输出的内容比较多,主要就是主从配置,分槽信息等。会问你是否安装这种方式建立集群,输入yes然后就可以建立集群了。

[root@run1 bin]# ./redis-trib.rb create --replicas 1 192.168.8.234:7000 192.168.8.234:7001 192.168.8.235:7000 192.168.8.235:7001 192.168.8.236:7000 192.168.8.236:7001

>>> Creating cluster

>>> Performing hash slots allocation on 6 nodes...

Using 3 masters:

192.168.8.236:7000

192.168.8.235:7000

192.168.8.234:7000

Adding replica 192.168.8.235:7001 to 192.168.8.236:7000

Adding replica 192.168.8.236:7001 to 192.168.8.235:7000

Adding replica 192.168.8.234:7001 to 192.168.8.234:7000

M: 100214611c0b977a148e3dc90b99cc11304ddc90 192.168.8.234:7000

   slots:10923-16383 (5461 slots) master

S: b33e10698aa52b2d4db7e177f533163c819d3174 192.168.8.234:7001

   replicates 100214611c0b977a148e3dc90b99cc11304ddc90

M: d3e99fff7dc569d9443baebccb977e670dd378f8 192.168.8.235:7000

   slots:5461-10922 (5462 slots) master

S: 6a1171f1ec484d51fbf98fb5f23b5fb6c745dce6 192.168.8.235:7001

   replicates d62a40345cffda3628ac51c8115fa09f7828ded1

M: d62a40345cffda3628ac51c8115fa09f7828ded1 192.168.8.236:7000

   slots:0-5460 (5461 slots) master

S: d310f0778ac5c5b5fe4307d01b7b2d2e7c2f9c6d 192.168.8.236:7001

   replicates d3e99fff7dc569d9443baebccb977e670dd378f8

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.8.234:7000)

M: 100214611c0b977a148e3dc90b99cc11304ddc90 192.168.8.234:7000

   slots:10923-16383 (5461 slots) master

   1 additional replica(s)

S: b33e10698aa52b2d4db7e177f533163c819d3174 192.168.8.234:7001

   slots: (0 slots) slave

   replicates 100214611c0b977a148e3dc90b99cc11304ddc90

M: d3e99fff7dc569d9443baebccb977e670dd378f8 192.168.8.235:7000

   slots:5461-10922 (5462 slots) master

   1 additional replica(s)

M: d62a40345cffda3628ac51c8115fa09f7828ded1 192.168.8.236:7000

   slots:0-5460 (5461 slots) master

   1 additional replica(s)

S: 6a1171f1ec484d51fbf98fb5f23b5fb6c745dce6 192.168.8.235:7001

   slots: (0 slots) slave

   replicates d62a40345cffda3628ac51c8115fa09f7828ded1

S: d310f0778ac5c5b5fe4307d01b7b2d2e7c2f9c6d 192.168.8.236:7001

   slots: (0 slots) slave

   replicates d3e99fff7dc569d9443baebccb977e670dd378f8

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.



3、可能遇到的错误:

  • 、in `call': ERR Slot 8579 is already busy (Redis::CommandError)

错误提示是

      slot插槽被占用了(这是 搭建集群前时,以前redis的旧数据和配置信息没有清理干净。)

解决方案是

用redis-cli 登录到每个节点执行  flushall  和 cluster reset  就可以了。

报错:

[root@run1 bin]# ./redis-cli -p 7000

127.0.0.1:7000> flushdb

OK

127.0.0.1:7000> cluster reset

OK

127.0.0.1:7000> exit

[root@run1 bin]# ./redis-cli -p 7001

127.0.0.1:7001> flushdb

OK

127.0.0.1:7001> cluster reset


  • 创建集群时一直处于"Waiting for the cluster to join...................................."的状态

    这个问题原因不知,但解决方法是在redis.conf文件中把bind 127.0.0.1本地环回口改为物理接口比如我修改成为bind 192.168.8.234 等。不要写 127.0.0.1了。



三、集群维护

1、集群登陆,注意我们要加入-c,否则就不是进入集群模式

./redis-cli -c -h 192.168.8.234  -p 7000


2、基本命令,可以看到不同set的key会分配到不同服务器的槽中的。

[root@run1 bin]# ./redis-cli -c -h 192.168.8.234  -p 7000

192.168.8.234:7000> set key1 v1

-> Redirected to slot [9189] located at 192.168.8.235:7000

OK

192.168.8.235:7000> set key2 v2

-> Redirected to slot [4998] located at 192.168.8.236:7000

OK

192.168.8.236:7000> get key1

-> Redirected to slot [9189] located at 192.168.8.235:7000

"v1"


3、其他常用命令

//集群(cluster)  

CLUSTER INFO 打印集群的信息  

CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。   

  

//节点(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)。   

  

//键 (key)  

CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。  

CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。  

CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。  



4、对集群进行重新分片

    现在, 让我们来试试对集群进行重新分片操作。

    在执行重新分片的过程中, 请让你的 example.rb 程序处于运行状态, 这样你就会看到, 重新分片并不会对正在运行的集群程序产生任何影响, 你也可以考虑将 example.rb 中的 sleep 调用删掉, 从而让重新分片操作在近乎真实的写负载下执行。

    重新分片操作基本上就是将某些节点上的哈希槽移动到另外一些节点上面, 和创建集群一样, 重新分片也可以使用 redis-trib 程序来执行。

    执行以下命令可以开始一次重新分片操作:

    $ ./redis-trib.rb reshard 127.0.0.1:7000



5、添加节点


1,新配置二个测试节点


//新增配置  

# cp redis-6379.conf redis-6378.conf && sed -i "s/6379/6378/g" redis-6378.conf  

# cp redis-6382.conf redis-6385.conf && sed -i "s/6382/6385/g" redis-6385.conf  

  

//启动  

# redis-server /etc/redis/redis-6385.conf > /var/log/redis/redis-6385.log 2>&1 &  

# redis-server /etc/redis/redis-6378.conf > /var/log/redis/redis-6378.log 2>&1 & 

 

2,添加主节点

# redis-trib.rb add-node 192.168.10.219:6378 192.168.10.219:6379  

注释:


192.168.10.219:6378是新增的节点

192.168.10.219:6379集群任一个旧节点


3,添加从节点

# redis-trib.rb add-node --slave --master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2 192.168.10.220:6385 192.168.10.219:6379  

注释:


--slave,表示添加的是从节点

--master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2,主节点的node id,在这里是前面新添加的6378的node id


192.168.10.220:6385,新节点

192.168.10.219:6379集群任一个旧节点



6、改变从节点的master


//查看一下6378的从节点  

# redis-cli -p 6378 cluster nodes | grep slave | grep 03ccad2ba5dd1e062464bc7590400441fafb63f2  

  

//将6385加入到新的master  

# redis-cli -c -p 6385 -h 192.168.10.220  

192.168.10.220:6385> cluster replicate 5d8ef5a7fbd72ac586bef04fa6de8a88c0671052  //新master的node id  

OK  

192.168.10.220:6385> quit  

  

//查看新master的slave  

# redis-cli -p 6379 cluster nodes | grep slave | grep 5d8ef5a7fbd72ac586bef04fa6de8a88c0671052  


7、删除节点

1,删除从节点

# redis-trib.rb del-node 192.168.10.220:6385 '9c240333476469e8e2c8e80b089c48f389827265'  


2,删除主节点

如果主节点有从节点,将从节点转移到其他主节点

如果主节点有slot,去掉分配的slot,然后在删除主节点


# redis-trib.rb reshard 192.168.10.219:6378 //取消分配的slot,下面是主要过程  

  

How many slots do you want to move (from 1 to 16384)? 1000 //被删除master的所有slot数量  

What is the receiving node ID? 5d8ef5a7fbd72ac586bef04fa6de8a88c0671052 //接收6378节点slot的master  

Please enter all the source node IDs.  

 Type 'all' to use all the nodes as source nodes for the hash slots.  

 Type 'done' once you entered all the source nodes IDs.  

Source node #1:03ccad2ba5dd1e062464bc7590400441fafb63f2 //被删除master的node-id  

Source node #2:done   

  

Do you want to proceed with the proposed reshard plan (yes/no)? yes //取消slot后,reshard  

新增master节点后,也进行了这一步操作,当时是分配,现在去掉。反着的。


# redis-trib.rb del-node 192.168.10.219:6378 '03ccad2ba5dd1e062464bc7590400441fafb63f2'  


参考网站:http://doc.redisfans.com/topic/cluster-tutorial.html