码迷,mamicode.com
首页 > 其他好文 > 详细

REDIS CLUSTER 搭建,扩容缩容基本原理

时间:2020-05-03 14:29:53      阅读:56      评论:0      收藏:0      [点我收藏+]

标签:通信   应该   搭建过程   led   基本   显示   column   ips   信息   

摘要

在redis4.0.14版本,是通过ruby的工具redis-trib.rb工具进行扩容缩容以及集群搭建的工作,然后到redis5.0后取消了这个工具的功能并合并到redis-cli中,这里就让我们了解一下redis-trib.rb工具在搭建集群和扩容缩容中到底做了什么把

源码在github 上搜索redis,第一个就是了,这里就不贴代码了

1. Redis4.0 不使用redis-trib.rb工具搭建cluster

1.1 redis redis-trib.rb create方法分析

步骤 作用
node ClusterNode.new(n) 初始化,n是node,对节点信息初始化
node.connect(:abort => true) 连接节点
node.assert_cluster 判断节点信息,看cluster_enabled是否开启
node.load_info 如果节点已经有slot,则对该节点执行addslot命令,设置节点的cluster info信息
node.assert_empty

验证该节点的cluster_known_nodes是否为1 和验证 该节点的db0是否为空

如果cluster_known_nodes不为1则认为已经加入其他集群,如果db0不为空则认为该节点不为空不能加入该集群

add_node(node) @nodes << node 把该node节点加入@nodes数组
把所有节点按以上流程走一遍,再开始执行下面
check_create_parameters

masters @nodes.length/(@replicas+1) 计算master 节点,@replicas代表每个主有多少个从

如果是一主二从的集群,master的结点数=用节点数/2+1

所以一主二从的集群起码要9个节点,才能搭建cluster

alloc_slots

先维护一个字典,每个node的ip为键,所有的nodes的信息为值(一个字典),把nodes加入字典中

ips[n.info[:host]= [if !ips[n.info[:host]]

ips[n.info[:host]] << n

选择命令的前3个作为master节点

计算每个每个节点分配多少槽(ClusterHashSlots.to_f / masters_count)

然后调用addslots方法,其实就是把要分配的slots 遍历加入节点的对象(一个字典)中的key[slots]中,每个master节点都执行一个分配槽的操作

show_nodes 输出槽的分配结果

 

1.2 搭建过程

## step 1

## 以第一点的配置启动6个节点

## redis-server /usr/conf/cluster/7000.conf

## redis-server /usr/conf/cluster/7001.conf

## .....................................................................

## redis-server /usr/conf/cluster/7005.conf

 

## step 2

## redis-cli -p 7001 -c   (随便进入一个集群)

## 执行cluster meet / redis-trib.rb add nodes 把其他节点加入集群

 技术图片

## 查看集群的节点信息

## cluster nodes

技术图片

 

 

## step 4

## 挑选前3个节点作为master

##  16384 / 3 = 5461.333 

## 先给第一个master几点分配 5461个节点

##  redis-cli -p 7001 -c cluster addslots {0..5460}

技术图片

 

 

## 第二个节点分配的位置的初始位置为5461,结束为5461+5461 =10922

## redis-cli -p 7003 -c cluster addslots {5461..10922}

技术图片

 

## 第三个节点分配的位置的初始位置为10923,last = 16384-1

## redis-cli -p 7000 -c cluster addslots {10923..16838}

 技术图片

 

 

## step 5

## 给master 节点设置slave节点

## 分别进入3个没有槽的节点 执行cluster replicate

## redis-cli -p 7002 -c cluster replicate 9222d226718a707c4517e634dfe38e81c026986c

## redis-cli -p 7005 -c cluster replicate 403b709820b1deeea8eab0744c76f928b53b7e86

## redis-cli -p 7004 -c cluster replicate 7bca1a86e03c7c176a8298c34ff363b7100d21d8

技术图片

 

 

## step 6 

## 查看每个节点的集群状态

## redis-cli -p 7000 -c cluster info

## redis-cli -p 7001 -c cluster info

## redis-cli -p 7002 -c cluster info

技术图片

 

 ## 确认每个节点的集群状态,因为加入A节点的槽部分不可用,A的cluster_state的状态会为fail,其他节点的clutser_state会显示ok

2.Redis4.0 不使用redis-trib.rb工具对集群进行扩容缩容

2.1 redis-trib.rb reshard 方法

ALL的分配方式顺序
作用

遍历所有节点,过滤掉slave的节点,和接收槽的节点

把剩余的节点加入sources数组中,作为槽的来源节点

 

多个槽来源的计算方式:

1.先对来源槽进行排序,

2 计算每个节点要移出多少个槽 (numslots.to_f/source_tot_slots*s.slots.length)

这样的处理方式会带来最终分配的slot与请求迁移的slot数量不一致

3. 计算出每个节点需要移出的槽数

4. 遍历每个节点的所需要移出的槽,加入move数组中

move = []

move << {:source=>s,slot=>slot}

要移动的槽全部放进数组中

numslots.to_f 总共要移动的槽数

source_tot_slots 所有来源节点的槽数

s.slots.length 单个来源节点拥有的槽数

没记错是入栈出栈的计算方式

先计算numslots.to_f/source_tot_slots

再算 *s.slots.length

target.r.cluster("setslot",slot,"importing",source.info[:name])

source.r.cluster("setslot",slot,"migrating",target.info[:name])

migrate ...迁移键

n.r.cluster("setslot",slot,"node",target.info[:name])

每个槽使用importing导出,然后再移动到接收槽上

源节点和目标节点都执行cluster setslot ... node ...

 

2.2 扩容介绍

## step 1

## redis-server 启动两个节点,一个主一个从

## redis-server /usr/conf/cluster/7006.conf

## redis-server /usr/conf/cluster/7007.conf

## netstat -lnp | grep redis

技术图片

## 新启动了两个节点

 

## step 2

## 进入集群中的任意带槽的节点节点

## redis-cli -p 7003 -c

## 把新启动的节点加入集群

## cluster meet 127.0.0.1 7006

## cluster meet 127.0.0.1 7007

## cluster nodes

技术图片

 

## 成功把两个节点加入集群

 

## step 3 扩容

## 扩容,给新的一个master 节点分配槽

## 多个来源节点的情况

## 遍历每个节点,计算每个节点应该移出多少个槽 (numslots.to_f/source_tot_slots*s.slots.length)

## numslots.to_f 总共要移动的槽数

## source_tot_slots 所有来源节点的槽数

## s.slots.length 单个来源节点拥有的槽数

## 循环每个slot:

## 接收节点执行 cluster setslot <slot> importing <node_id>   (node_id为源节点id)

## 来源节点执行 cluster setslot <slot> migrating <node_id>    (node_id为接收节点id)

## 源节点执行 cluster countkeysinslot <slot> 查看要移动的槽 有没有键

## 如果有 则 继续执行 cluster getkeysinslot <slot> <count>  查看slot节点的多少个key值, 如果上一步槽的键数量为空跳过此步骤

## 然后执行 MIGRATE 源节点ip 源节点port "" 0 5000 KEYS key1 key2 key3  把键先迁移,执行这条命令后该键不可读不可写

## 分别在源节点和接收节点执行 cluster setslot <slot> node <node_id>   

## 现在看 主要在接收节点上执行 cluster setslot ...node ...命令,只有在接收节点上面执行后会跟新接收节点的epoch 版本号,然后发消息跟其他节点说该slot已经归我管了,如果epoch比接收信息的节点高,接收信息的节点会跟新该slot的状态

## 而源节点上面执行cluster setslot .... node ...命令只移除mirating flag 并不会更新版本号

## 那么问题来了,那importing 和migrating 步骤不就可以省略吗,那源节点也没必要执行cluster setslot ... node ...命令了(其实并不是这样,详见测试)

 

2.3 扩容实例

技术图片

把7373 节点从 7004 移动到7009

 

## step 1

## redis-cli -p 7009 -c cluster setslot 7373 importing cd8cd114215e4c2869d6d31ae7fe5f5cff922ed3

## 从其他节点观察槽信息

## redis-cli -p 7009 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 ## 从7009 节点上看到设置了一个importing flag (-<-)

 

## redis-cli -p 7004 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 ## 在7004 上面没有变化

 

## redis-cli -p 7003 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 ## 在7003 上面没有变化

 

##往槽7373 插入数据

技术图片

 

 ## 说明槽还在 7004 上面

 

## step 2

## redis-cli -p 7004 -c cluster setslot 7373 migrating 273289d0a17cd30fecc7a3db6fb2fd1cb06b3e55

## 从其他节点观察槽信息

## redis-cli -p 7009 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

## 7009 上面仍然只看到自己身上只有一个importing flag,7373槽仍然在7004 上面

 

## redis-cli -p 7004 -c cluster nodes | grep master | sort -t ‘ ‘ -k2 技术图片

## 7004 上面看到自己多出一个mirating flag,7373槽仍然在7004 上面

 

## redis-cli -p 7003 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 ## 7003 仍然没变化

 

## redis-cli -p 7003 -c get gw 

技术图片

 

 ## 7373槽仍在在7004上面

 

## step 3

## redis-cli -p 7004 -c cluster countkeysinslot 7373

## 查看槽7373 有多少个key,必须在源节点上面执行

技术图片

 

## 7373 上面有一个key

 

 

## step 4

## redis-cli -p 7004 -c cluster getkeysinslot 7373 1

技术图片

 

## 7373槽上面只有一个key gw,必须在源节点上面执行

 

## step 5

## redis-cli -p 7004 -c MIGRATE 127.0.0.1 7009 "" 0 5000 KEYS gw

## 把槽7373的键从7004 移动到 7009

## redis-cli -p 7004 -c get gw

## redis-cli -p 7004 -c set gw qwes

技术图片

 

## 执行完migrate 后键也不可访问

## 因为执行 setslot migrating 和setslot importing之后,旧的键可以在源节点上访问,但是新的键设置只能在新节点上面执行asking后执行设置新键命令才能成功

## 这样保证了 setslot migrating 和setslot importing之后不会在源节点上设置新键值对,避免setslot ,,,node,,, 后新键值丢失

## 由于mirate命令命令把旧键移动到接收节点上去,所以现在源节点上已经没有旧键了,这个时候,所有键的访问都必须在接收节点上执行asking后执行操作

## 例如:

## redis-cli -p 7009 -c

## asking

## set  sand aksnd

## 才会成功

 

## step 6

## redis-cli -p 7004 -c cluster setslot 7373 node 273289d0a17cd30fecc7a3db6fb2fd1cb06b3e55

## redis-cli -p 7004 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

## 从7004节点上面看,原本7004 上面的migrating flag 没有了,7373槽已经移动到 7009 上面去

 

## redis-cli -p 7009 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 

## 从 7009 上面看 importing flag 还没被消除, 7373slot 仍然在7004上面

## redis-cli -p 7003 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 ## 从7003 上面看 7373 仍然在 7004 上面

 

## get gw

## set gw asd

技术图片

 

## 在 7003和7004 上面反复横跳

##注意,这里先在源节点上面执行setslot.... node....命令

## 形成原因

技术图片

 

 ## 无论从哪个节点上面访问都会导致这种情况,这是由于每个节点信息不同步 或者说数据不一致导致的

 

## step 7

## redis-cli -p 7009 -c cluster setslot 7373 node 273289d0a17cd30fecc7a3db6fb2fd1cb06b3e55

## 从其他节点查看slot7373的信息

## redis-cli -p 7009 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 ## 从7009节点上面看,原本7009上面的importing flag 没有了,7373槽已经移动到 7009 上面去,迁移成功

 

## redis-cli -p 7004 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 ## 从7004 节点上面看,7373slot 已经迁移成功

 

## redis-cli -p 7003 -c cluster nodes | grep master | sort -t ‘ ‘ -k2

技术图片

 

 ## 从7003上面看,7373slot已经迁移成功

 

## get gw 

## set ge asds

技术图片

 

 ## 数据已经可读可写

 ## 反复横跳现象已经消失,只要先在接收节点上面执行setslot ... node  就不会出现反复横跳现象

 

## step 8

## 观察日志 发现 只有接收slot 的节点 执行setslot ... node 命令 才会更新epoch 版本号,其他节点不会更新epoch,

 技术图片

 

 

## 节点之间通信的时候,会带着epoch版本号

## 加入 节点A接收了槽7373,更新了版本号到57,然后通信时A 给节点B发消息,说7373槽已经归我管了

## 现在有两种情况,一是节点B的epoch 比57 高,二是节点B的epoch版本号比57低

## 情况一:不理会节点A 的信息,这就导致数据不一致,节点B仍然认为槽7373 归源节点管

## 情况二: 更新信息,同步认为槽7373已经归节点A 管

 

REDIS CLUSTER 搭建,扩容缩容基本原理

标签:通信   应该   搭建过程   led   基本   显示   column   ips   信息   

原文地址:https://www.cnblogs.com/start-from-zero/p/12821608.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!