深入Redis之 redis cluster 集群原理 (九)-张柏沛IT博客

正文内容

深入Redis之 redis cluster 集群原理 (九)

栏目:Linux 发布时间:2020-03-01 00:03 浏览量:197

所谓的分布式集群就是:加机器,所有的数据分散的存放到每一台机器

redis Cluster是redis内部提供的一种分布式集群功能


为什么需要分布式集群
1.并发量需求
单机的redis的性能可以达到QPS每秒10万
但是更大的并发量需要分布式集群分散redis请求

2.数据量需求(扩容)
一个正常的企业级应用所在的单台机器其内存在16G~256G间
如果需要将大量数据都存在内存,就需要更多机器进行扩容


分区规则:
最常见的就是顺序分区(即范围分区 1~100中1~33放第一个分区,34~66第二个分区,67~100第三个分区)和哈希分区(类似于取模)

对比:
哈希分布:数据分散度高,键值分布业务无关,无法顺序访问,支持批量操作
顺序分布:数据分散度易倾斜,键值业务相关,可顺序访问


redis cluster属于哈希分片(分布)



哈希分布主要有三种方式:


节点取余分区

对key进行hash()处理后的结果取余数决定其所在的节点
优势:简单明了
劣势:扩容时会导致大批量的数据迁移问题(节点数从3变为4,id为3的数据要从节点1迁移到节点3)。

如果真的要扩容建议翻倍扩容,可以减少迁移量

不建议使用取余分区


一致性哈希分区
是对取余算法的一个优化。它将数据范围看成一个token环,对key进行hash处理的值会落在环上,每一个key会存储在离环上最近的那个节点。
优势:当进行扩容时,只会有少量的数据的迁移。尤其是当节点数比较大的时候,迁移的数据量占比会越少
劣势:可能会导致负载不均衡,新加的节点的流量会比较少


虚拟槽分区
redis cluster就是使用这种算法
每一个redis节点会被分配一个槽范围,每一个槽范围对应着一个数字范围。总的范围默认是0~16383

如果有五个节点,每个节点分配一个槽范围,第一个节点的槽范围是0~3275,第二个节点是3276~6553,.....

查找或写入数据时,键值key进行hash运算得到的hash值对16383取余得到的数就是这个key所在的节点位置。


=======================================


redis cluster的基本架构


​​​​​​​
1.多节点

2.复制
集群中的节点有主有从,每一台主节点都有至少一台从节点

3.meet
每一个集群节点都是互相通信的(通过meet操作),这样每一台节点就可以知道其他所有节点的槽范围

4.指派槽
需要给每一个节点指定一个槽范围,redis会根据key按照hash运算得到的取模值找到对应槽所在的节点


redis cluster的安装
两种方法: 原生命令安装和官方工具安装(ruby)


原生命令安装
1.配置启动redis

port 6379
daemonize yes
dir /tmp/redis
dbfilename dump-6379.conf
logfile 6379.log 
cluster-enabled yes    # 表示该节点是集群节点
cluster-config-file nodes-6379.conf     # 指定集群节点配置文件
cluster-node-timeout 15000  # 节点主观下线的超时时间,使用默认值就好
cluster-require-full-coverage no   # 如果有一台节点挂掉,整个集群的节点就不提供服务,默认yes,要改为no


# 开启所有集群节点
redis-server redis-6379.conf 
redis-server redis-6380.conf 
redis-server redis-6381.conf 
redis-server redis-6382.conf 
redis-server redis-6383.conf 
redis-server redis-6384.conf 

这里做实验所以所有节点都放一台机器上。真实项目中是一台机器放一个redis节点。

这里六台节点,三主三从


2.meet操作让所有节点相互通信

redis-cli -p 6379 cluster meet 127.0.0.1 6380
redis-cli -p 6379 cluster meet 127.0.0.1 6381
redis-cli -p 6379 cluster meet 127.0.0.1 6382
redis-cli -p 6379 cluster meet 127.0.0.1 6383
redis-cli -p 6379 cluster meet 127.0.0.1 6384

只要让一台节点meet其他节点,那么其他所有节点之间都能互相通信(6379可与6382通信,6381可与6384通信)

3.为每一个主节点分配槽

redis-cli -p 6379 cluster addslots slot {0...5461}
redis-cli -p 6380 cluster addslots slot {5462...10922}
redis-cli -p 6381 cluster addslots slot {10923...16383}


4.设置主从

redis-cli -p 6382 cluster replicate ${node-id-6379}     # 主为6379,从为6382
redis-cli -p 6383 cluster replicate ${node-id-6380}
redis-cli -p 6384 cluster replicate ${node-id-6381}

${node-id-6381}是6381的node-id,node-id是 cluster nodes 命令执行结果的第一列

原生命令主要是为了让我们了解redis cluster的一个原理和过程。实际生产中,会使用官方提供的ruby实现。


==========================================

实验开始:
4个集群节点:
主:127.0.0.1 7000
主:127.0.0.1 7001
从:127.0.0.1 7002
从:127.0.0.1 7003

配置内容如下:

port 7000
daemonize yes
logfile "7000.log"
pidfile "redis_7000.pid"
dir "/usr/local/redis/test"
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-require-full-coverage no


1.开启节点
redis-server ./redis-7000.conf
redis-server ./redis-7001.conf
redis-server ./redis-7002.conf
redis-server ./redis-7003.conf

查看redis节点的集群情况
redis-cli -p 7000 cluster nodes
结果
3866c0186d88b0c785281b49010169ba76ffc7db :7000@17000 myself,master - 0 0 0 connected 5798

由于还没有进行meet操作所以只有一条数据。


redis-cli -p 7000 cluster info
结果
cluster_state:ok            # 集群状态    
cluster_slots_assigned:1    # 集群总体被分配的槽的总个数
cluster_slots_ok:1
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1   # 连通的集群个数,由于未meet,所以为1
cluster_size:1      # 集群节点个数
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0


此时尝试在其中一台集群中写入数据


2.meet操作 
redis-cli -p 7000 cluster meet 127.0.0.1 7001
redis-cli -p 7000 cluster meet 127.0.0.1 7002
redis-cli -p 7000 cluster meet 127.0.0.1 7003

查看redis节点的集群情况
redis-cli -p 7000 cluster nodes

结果
fef85a301c532f30828246e324dfc43f40655c99 127.0.0.1:7003@17003 slave 3866c0186d88b0c785281b49010169ba76ffc7db 0 1582969747224 1 connected
3866c0186d88b0c785281b49010169ba76ffc7db 127.0.0.1:7000@17000 myself,master - 0 1582969747000 1 connected 5798
42b52e00f7f2387d881ee794e2558ac92d3d27e8 127.0.0.1:7001@17001 slave 3866c0186d88b0c785281b49010169ba76ffc7db 0 1582969748000 1 connected
a044f31e35f8e32334a5fee4faeaa88fcbe8d041 127.0.0.1:7002@17002 slave 3866c0186d88b0c785281b49010169ba76ffc7db 0 1582969748227 1 connected


3.分配槽范围
要写一个脚本来完成

addslots.sh如下

#!/bash/sh

start=$1
end=$2
port=$3


for slot in `seq ${start} ${end}`
do
        echo "slot:${slot}"
        redis-cli -p ${port} cluster addslots ${slot}
done


#我们只需要对主节点分配槽
sh addslots.sh 0 8191 7000
sh addslots.sh 8192 16383 7001


#分配槽范围完毕,查看分配情况:
redis-cli -p 7001 cluster nodes

结果

fef85a301c532f30828246e324dfc43f40655c99 127.0.0.1:7003@17003 slave 3866c0186d88b0c785281b49010169ba76ffc7db 0 1582970971368 1 connected
42b52e00f7f2387d881ee794e2558ac92d3d27e8 127.0.0.1:7001@17001 myself,slave 3866c0186d88b0c785281b49010169ba76ffc7db 0 1582970971000 0 connected 8192-16383
a044f31e35f8e32334a5fee4faeaa88fcbe8d041 127.0.0.1:7002@17002 slave 3866c0186d88b0c785281b49010169ba76ffc7db 0 1582970973374 1 connected
3866c0186d88b0c785281b49010169ba76ffc7db 127.0.0.1:7000@17000 master - 0 1582970972371 1 connected 0-8191

注意第二行有一个 8192-16383
第四行有一个 0-8191
表示 7001和7000 分配的槽的范围


redis-cli -p 7001 cluster info

结果
cluster_state:ok
cluster_slots_assigned:16384        # 集群的总的槽数
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:4
cluster_size:1
cluster_current_epoch:1
cluster_my_epoch:1
cluster_stats_messages_ping_sent:1554
cluster_stats_messages_pong_sent:1528
cluster_stats_messages_meet_sent:1
cluster_stats_messages_sent:3083
cluster_stats_messages_ping_received:1526
cluster_stats_messages_pong_received:1555
cluster_stats_messages_meet_received:2
cluster_stats_messages_update_received:1
cluster_stats_messages_received:3084

4.集群主从复制
作者执行:
redis-cli -p 7002 cluster replicate 3866c0186d88b0c785281b49010169ba76ffc7db    # 最后一列这是 7000的node id 
redis-cli -p 7003 cluster replicate fef85a301c532f30828246e324dfc43f40655c99    # 这是 7001的node id 

redis-cli -p 7001 cluster nodes


但是其实在 meet 那一步的时候,主从关系就已经建立好了。7000是主,7001~7003都是从。
所以这里想让7003同步7001也就办不到了。可能新版本redis是这样的。



=============================================

ruby构建redis cluster 集群 

ruby下载 http://www.ruby-lang.org/zh_cn/downloads/

下载安装包后:
./configure --prefix=/usr/local/ruby
make && make install

ruby -v 可以查看ruby的版本

由于系统本身自带了ruby,所以要将新安装的ruby命令覆盖原本的ruby
cp /usr/local/ruby/bin/ruby /usr/local/bin
cp /usr/local/ruby/bin/ruby /usr/bin

安装rubygem redis 这是ruby的redis客户端
wget https://rubygems.org/downloads/redis-4.1.3.gem   # redis的gem版本可以在https://rubygems.org中查看
gem install -l redis-4.1.3.gem

如果没有gem命令则 yum install -y gem

安装redis-trib.rb,这是redis官方的一个用于搭建redis集群工具,是基于ruby的
# 从redis安装包目录中复制redis-trib.rb文件即可
cd ~/redis.5.0.7 && cp redis-trib.rb /usr/local/redis/bin/

接下来使用 redis-trib.rb 进行redis cluster部署


1.先启动所有节点(请先删除rdb文件再重启)
redis-server ./redis-7000.conf
redis-server ./redis-7001.conf
redis-server ./redis-7002.conf
redis-server ./redis-7003.conf
redis-server ./redis-7004.conf
redis-server ./redis-7005.conf


2.部署集群
redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

其中 --replicas 1 表示每一个集群中的主节点都有一个从节点,此时会自动将7002作为7000的从节点,7003作为7001的从节点

他会自动进行集群节点的meet操作和分配槽

但是在新版本的redis中,redis-cli本身就支持一步建立redis cluster部署,无需安装redis-trib。在redis 5.0 +的版本 中,redis-trib已经废弃。

而且redis cluster的搭建至少要有3台主节点,所以要至少部署6台节点


2. 部署集群(修改)
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1

信息如下

Master[0] -> Slots 0 - 5460         #主节点的槽范围
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:7004 to 127.0.0.1:7000     # 集群主从复制信息
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7003 to 127.0.0.1:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 422f7a809e464bc9fab3ef535394e3eacf0f4a67 127.0.0.1:7000      # node-id 节点ip和port 槽范围 是主/从节点
   slots:[0-5460] (5461 slots) master
M: 81c66987868397428ffde697e9f5b1cdf9989bc5 127.0.0.1:7001
   slots:[5461-10922] (5462 slots) master
M: 2de72ccddcd0d68c65e2d1f6fbd1637736bafb9e 127.0.0.1:7002
   slots:[10923-16383] (5461 slots) master
S: 84dae996ae9f144539397c79e213d707953dc614 127.0.0.1:7003
   replicates 2de72ccddcd0d68c65e2d1f6fbd1637736bafb9e
S: 7aef0ac6cfea3ea9883d61d4f85e9013ee9e920c 127.0.0.1:7004
   replicates 422f7a809e464bc9fab3ef535394e3eacf0f4a67
S: bb071d1206a88c219a3e7de81fab1305ecdc81fe 127.0.0.1:7005
   replicates 81c66987868397428ffde697e9f5b1cdf9989bc5


   
   这里把谁是主节点谁是从节点,每个主节点分配的槽都列的很清楚
   
   
==========================================

原生命令在实际生产中几乎不会用到,因为太麻烦了。但是通过原生命令安装可以让我们清楚redis cluster的架构

使用官方工具安装则简单高效,meet操作和槽分配都自动完成


如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > 深入Redis之 redis cluster 集群原理 (九)

热门推荐
推荐新闻