Docker下搭建Redis集群并实现动态扩/缩容
一、Redis集群方案的简单介绍
Redis集群的方案一般分为三种:
- 哈希取余分区
- 一致性哈希算法分区
- 哈希槽分区(本文介绍的就是这种)
1、哈希取余分区:
优点:
简单粗暴,只要提前预估好数据量,然后规划好节点,例如:3台、30台、300台节点,就能保证未来一段时间内的数据支撑。

缺点:
事先规划好节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。如果某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。
2、一致性哈希算法分区:
优点:
容错性:假设Node C宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据,并且这些数据会转移到D进行存储。

扩展性:数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那受到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。

优点总结:加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。
缺点:
Hash环的数据倾斜问题,一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中在某一台服务器上)问题。数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果,造成了分区中数据倾斜不一致性的问题。

3、哈希槽分区
由于一致性哈希分区存在数据倾斜不一致性的问题,故引入了槽的概念。Redis 集群中内置了 16384 个哈希槽,Redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。当需要在 Redis 集群中放置一个 key-value时,Redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,也就是映射到某个节点上。

优点:极大地方便了集群做线性扩展,以及实现平滑的扩容或缩容。
本文就是对Redis“哈希槽分区”的搭建进行介绍,具体步骤请看下面的操作。
二、环境介绍
- Docker版本:Docker version 24.0.5, build ced0996
- Centos:CentOS Linux release 7.9.2009 (Core)
- Redis:docker中的redis:latest版
三、哈希槽分区的搭建与测试
1、使用命令多次创建Redis容器
# 创建Redis集群容器
docker run -d --name redis-node-1 --net host --privileged=true -v /mydata/redis/share/redis-node-1:/data redis --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name redis-node-2 --net host --privileged=true -v /mydata/redis/share/redis-node-2:/data redis --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name redis-node-3 --net host --privileged=true -v /mydata/redis/share/redis-node-3:/data redis --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name redis-node-4 --net host --privileged=true -v /mydata/redis/share/redis-node-4:/data redis --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name redis-node-5 --net host --privileged=true -v /mydata/redis/share/redis-node-5:/data redis --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name redis-node-6 --net host --privileged=true -v /mydata/redis/share/redis-node-6:/data redis --cluster-enabled yes --appendonly yes --port 6386 # 参数介绍
docker run # 创建并运行docker容器实例
--name redis-node-1 # 容器名字
--net host # 使用宿主机的IP和端口,默认
--privileged=true # 获取宿主机root用户权限
-v /mydata/redis/share/redis-node-1:/data # 容器卷,宿主机地址:docker内部地址
redis # redis镜像和版本号(有版本可以 redis:6.0.8)
--cluster-enabled yes # 开启redis集群
--appendonly yes # 开启持久化
--port 6381 # redis端口号

2、随机进入一个Redis容器,进行主从的配置
# 进入Redis节点1
docker exec -it redis-node-1 /bin/bash # 进入节点1后构造主从。只有进入docker容器后才能执行以下命令,且注意自己的真实IP地址。
redis-cli --cluster create 192.168.152.134:6381 192.168.152.134:6382 192.168.152.134:6383 192.168.152.134:6384 192.168.152.134:6385 192.168.152.134:6386 --cluster-replicas 1 --cluster create # 构建集群
--cluster-replicas 1 # 表示为每个master创建一个slave节点


3、查看集群状态
进入Redis后【cluster info】所展示的信息

进入Redis后【cluster nodes】所展示的信息,从下图中可以得知【主6381 - 从6385;主6382 - 从6386;主6383 - 从6384】。

从下图中可以看出6381是主服务器,6385是从服务器。6385是挂在6381的下面(6381和6385是一一对应)

4、数据的存储
通过【redis-cli -p 6381】命令进入redis,在存储信息的时候会发现哈希槽不匹配,不能存储数据。如下图所示:

我们在连接redis的时候需要添加一个参数,才能正确的选择存储路由,防止数据存储失败。正确的命令为【redis-cli -p 6381 -c】

查看集群的数据信息。通过上图可以得知下图的数据6381服务成功设置了2个数据,6383服务成功设置了1个数据。
# 192.168.152.134:6381 随便哪个redis端口都可以
redis-cli --cluster check 192.168.152.134:6381

5、容错切换和迁移
# 停止redis-node-1,查看集群状态
docker stop redis-node-1
从下图可以看出,redis-node-1已经停止了,节点状态已经是【fail】。从2-3中可以得知6381(主)和6385(从)是主从关系,现在6381(主)挂机了,6385(从)上位变成了master。

节点redis-node-1停止后,我们依然可以获取到之前在redis-node-1中设置的 k2 和 k3 信息,因为6381(主)和6385(从)是主从关系。说明我们配置主从和集群是正确的。

重新启动redis-node-1,再次查看集群信息。原来6381是主,6385是从。6381停止后,6385就变成了主,当再次启动6381时他就变成了从机。这时的主从关系是6385为主,6381为其从。如下图所示。

6、主从扩容案例
由于数据压力我们现在要对redis集群进行扩容,由原来的三主三从扩充到四主四从。
# 添加两台redis服务,分别是6387和6388
docker run -d --name redis-node-7 --net host --privileged=true -v /mydata/redis/share/redis-node-7:/data redis --cluster-enabled yes --appendonly yes --port 6387 docker run -d --name redis-node-8 --net host --privileged=true -v /mydata/redis/share/redis-node-8:/data redis --cluster-enabled yes --appendonly yes --port 6388 # 进入6387的redis节点
docker exec -it redis-node-7 /bin/bash # 将新增的6387作为master节点加入集群(加入成功后如下图)
# 命令格式:redis-cli --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381
# 6387 就是将要作为master新增的节点
# 6381 就是原来集群节点里面的带头大哥(相当于这个集群的代表),表示6387要加入到6381的组织集群当中
redis-cli --cluster add-node 192.168.152.134:6387 192.168.152.134:6381

1、使用命令检查集群情况
# [192.168.152.134]是宿主机的真是IP地址
redis-cli --cluster check 192.168.152.134:6381

2、重新分派槽号
# 从6381所代表的redis集群中分配
# 命令:redis-cli --cluster reshard IP地址:端口号
# reshard 表示分配槽位
redis-cli --cluster reshard 192.168.152.134:6381




3、再次使用命令检查集群情况
# [192.168.152.134]是宿主机的真是IP地址
redis-cli --cluster check 192.168.152.134:6381

4、为主节点6387分配从节点6388
# 命令格式:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
# 7364769634930d427dc19938878f4d45da46bd5f 这个是6387的编号,各位需要按照自己的实际情况来 redis-cli --cluster add-node 192.168.152.134:6388 192.168.152.134:6387 --cluster-slave --cluster-master-id 7364769634930d427dc19938878f4d45da46bd5f

5、分配节点后,再次用命令查看集群情况

7、主从缩容案例
目前的主从结构如下图。现在我们要缩容,把之前添加的6387和6388这对主从删除。

1、现在6387是主,6388是从,先删除从服务(6388)
# 先使用命令进入任意节点,我这里是进入了节点1
docker exec -it redis-node-1 bash # 检查集群情况,获得6388的节点ID
redis-cli --cluster check 192.168.152.134:6381 # 将6388从集群中删除
# 命令:redis-cli --cluster del-node ip:端口 6388节点ID
redis-cli --cluster del-node 192.168.152.134:6388 38974c5e6654f7f8c9f05e19d6412c31383bf681 # 删除后再次检查一下,6388被删除了,只剩下7台机器了。
redis-cli --cluster check 192.168.152.134:6381



2、接下来删除主库6387。先将6387的槽号清空,再重新分配槽号,槽号可以任意分配给其他任意主库,本例将清出来的槽号都给6382。
# 重新分配槽号
redis-cli --cluster reshard 192.168.152.134:6381 # 分配好后再次查看集群信息
redis-cli --cluster check 192.168.152.134:6381



3、槽位分配完成后,将6387删除
# 删除节点的命令:redis-cli --cluster del-node ip:端口 节点ID
redis-cli --cluster del-node 192.168.152.134:6387 7364769634930d427dc19938878f4d45da46bd5f # 删除后再次查看集群情况
redis-cli --cluster check 192.168.152.134:6381

Docker下搭建Redis集群并实现动态扩/缩容的更多相关文章
- Windows下搭建Redis集群
Redis集群: 如果部署到多台电脑,就跟普通的集群一样:因为Redis是单线程处理的,多核CPU也只能使用一个核, 所以部署在同一台电脑上,通过运行多个Redis实例组成集群,然后能提高CPU的利用 ...
- Redis集群搭建(转自一菲聪天的“Windows下搭建Redis集群”)
配置Redis参考:http://blog.csdn.net/zsg88/article/details/73715947 使用Ruby配置集群参考:https://www.cnblogs.com/t ...
- Windows下 搭建redis集群
Windows下搭建redis集群教程 一,redis集群介绍 Redis cluster(redis集群)是在版本3.0后才支持的架构,和其他集群一样,都是为了解决单台服务器不够用的情况,也防止了主 ...
- windows环境下搭建Redis集群
转载请注明出处,原文章地址: https://www.cnblogs.com/tommy-huang/p/6240083.html Redis集群: 如果部署到多台电脑,就跟普通的集群一样:因为Red ...
- Windows下搭建REDIS集群
Redis集群: 如果部署到多台电脑,就跟普通的集群一样:因为Redis是单线程处理的,多核CPU也只能使用一个核, 所以部署在同一台电脑上,通过运行多个Redis实例组成集群,然后能提高CPU的利用 ...
- linux系统centOS7下搭建redis集群中ruby版本过低问题的解决方法
问题描述: 在Centos7中,通过yum安装ruby的版本是2.0.0,但是如果有些应用需要高版本的ruby环境,比如2.2,2.3,2.4... 那就有点麻烦了,譬如:我准备使用redis官方给的 ...
- 从零开始学习docker之在docker中搭建redis(集群)
docker搭建redis集群 docker-compose是以多容器的方式启动,非常适合用来启动集群 一.环境准备 云环境:CentOS 7.6 64位 二.安装docker-compose #需要 ...
- centos下搭建redis集群
必备的工具: redis-3.0.0.tar redis-3.0.0.gem (ruby和redis接口) 分析: 首先,集群数需要基数,这里搭建一个简单的redis集群(6个redis实 ...
- Windows环境下搭建Redis集群(Redis-x64-3.2.100)
一 .前期准备Redis.Ruby语言运行环境.Redis的Ruby驱动redis-xxxx.gem.创建Redis集群的工具redis-trib.rb 二.安装配置redisredis下载地址 ht ...
- Redis → Windows下搭建redis集群
一,redis集群介绍 Redis cluster(redis集群)是在版本3.0后才支持的架构,和其他集群一样,都是为了解决单台服务器不够用的情况,也防止了主服务器宕机无备用服务器,多个节点网络互联 ...
随机推荐
- Go中字符串处理:fmt.Sprintf与string.Builder的比较
在Go语言中,我们通常会遇到两种主要的方式来处理和操作字符串:使用fmt.Sprintf函数和string.Builder类型.尽管两者都可以实现字符串的格式化和连接,但它们在性能和用法上有一些关键区 ...
- c和c++编译器之gcc和mingw
三大编译器:gcc,llvm,clang 什么是gcc? gcc 官方网站:https://gcc.gnu.org GCC(GNU Compiler Collection,GNU编译器套件),是由 G ...
- 从零开始匹配vim(2)——快捷键绑定
如果说 vim有什么最吸引人,我想vim允许你自由的定义各种快捷键算是一个原因吧.你可以通过绑定各种快捷键来使经常使用的功能更加便利.通俗的讲,快捷键映射就是我按下某个键,我想让vim将它当成另一个键 ...
- 推荐系统[四]:精排-详解排序算法LTR (Learning to Rank)_ poitwise, pairwise, listwise相关评价指标,超详细知识指南。
0.前言召回排序流程策略算法简介 推荐可分为以下四个流程,分别是召回.粗排.精排以及重排: 召回是源头,在某种意义上决定着整个推荐的天花板: 粗排是初筛,一般不会上复杂模型: 精排是整个推荐环节的重中 ...
- 3.1 C/C++ 使用字符与指针
C/C++语言是一种通用的编程语言,具有高效.灵活和可移植等特点.C语言主要用于系统编程,如操作系统.编译器.数据库等:C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统.图形用户界面 ...
- C/C++ x64 Inline Hook 代码封装
Hook 技术常被叫做挂钩技术,挂钩技术其实早在DOS时代就已经存在了,该技术是Windows系统用于替代DOS中断机制的具体实现,钩子的含义就是在程序还没有调用系统函数之前,钩子捕获调用消息并获得控 ...
- SqlDapperEasyUtil:.NET CORE下的Dapper封装操作类
之前介绍了基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil,这个在.NET FX下还是比较好用的,现在都流行.NET CORE,故我这边再次进行精简修改,以便适应.NET ...
- RocketMQ—RocketMQ发送同步、异步、单向、延迟、批量、顺序、批量消息、带标签消息
RocketMQ-RocketMQ发送同步.异步.单向.延迟.批量.顺序.批量消息.带标签消息 发送同步消息 生产者发送消息,mq进行确认,然后返回给生产者状态.这就是同步消息. 前文demo程序就是 ...
- 一键跳转组件所在的文件与具体行数,提升排查效率,分享几个 React Developer Tools 使用小技巧
壹 ❀ 引 React Developer Tools对于很多开发同学可能就是一个检查组件props传递对不对的工具,但事实上它的功能比我们想象的强大.比如我们日常排查问题,常常会遇到想知道某个页面某 ...
- NC210981 mixup2混乱的奶牛
题目链接 题目 题目描述 混乱的奶牛 [Don Piele, 2007] Farmer John的 N(4 <= N <= 16) 头奶牛中的每一头都有一个唯一的编号 \(S_i (1 & ...