百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

手把手教你搭建Redis集群(redis-cli 创建集群)

wptr33 2025-02-03 15:28 24 浏览

大家好,我是可乐,一个专注原创,乐于分享的程序猿。本系列教程持续更新,可以微信搜索「 IT可乐 」第一时间阅读。回复《电子书》有我为大家特别筛选的海量免费书籍资料

在上一篇博客我们介绍了------Redis哨兵(Sentinel)模式,哨兵模式主要是解决高可用问题,在master节点宕机时,slave节点能够自动切换成为master节点

本篇博客我们来介绍Redis的另外一种模式------集群模式.

PS:我这里搭建演示的版本是redis-5.0.5,这个版本对于集群搭建会有很大的简化,比如最常用的redis-trib.rb脚本功能已经集成到redis-cli工具中了,具体下面会详细介绍。

1、为什么需要集群?

①、并发量

通常来说,单台Redis能够执行10万/秒的命令,这个并发基本上能够满足我们所有需求了,但有时候比如做离线计算,为了更快的得出结果,有时候我们希望超过这个并发,那这个时候单机就不满足我们需求了,就需要集群了.

②、数据量

通常来说,单台服务器的内存大概在16G-256G之间,前面我们说Redis数据量都是存在内存中的,那如果实际业务要保存在Redis的数据量超过了单台机器的内存,这个时候最简单的方法是增加服务器内存,但是单台服务器内存不可能无限制的增加,纵向扩展不了了,便想到如何进行横向扩展.这时候我们就会想将这些业务数据分散存储在多台Redis服务器中,但是要保证多台Redis服务器能够无障碍的进行内存数据沟通,这也就是Redis集群.

2、数据分区方式

对于集群来说,如何将原来单台机器上的数据拆分,然后尽量均匀的分布到多台机器上,这是我们创建集群首先要考虑的一个问题,通常来说,有如下两种数据分区方式.

①、顺序分布

比如我们有100W条数据,有3台服务器,我们可以将100W/3的结果分别存储到三台服务器上,如下所示:

  特点:键值业务相关;数据分散,但是容易造成访问倾斜;支持顺序访问;支持批量操作

②、哈希分布

同样是100W条数据,有3台服务器,通过自定义一个哈希函数,比如节点取余的方法,余数为0的存在第一台服务器,余数为1的存在第二台服务器,余数为2的存储在第三台服务器.如下所示:

  特点:数据分散度高;键值分布与业务无关;不支持顺序访问;支持批量操作。

3、一致性哈希分布

问题:对于上面介绍的哈希分布,大家可以想一下,如果向集群中增加节点,或者集群中有节点宕机,这个时候应该怎么处理?

①、增加节点

  如上图所示,总共10个数据通过节点取余hash(key)%/3 的方式分布到3个节点,这时候由于访问量变大,要进行扩容,由 3 个节点变为 4 个节点。

我们发现,如图所示,数据除了标红的1 2 没有进行迁移,别的数据都要进行变动,达到了80%,如果这时候并发很高,80%的数据都要从下层节点(比如数据库)获取,会给下层节点造成很大的访问压力,这是不能接受的。

即使我们进行翻倍扩容,从3个节点增加到6个节点,其数据迁移也在50%左右。

②、删除节点

  上图其实不管是哪一个节点宕机,其数据迁移量都会超过50%。基本上也是我们所不能接受的。

那么如何使得集群中新增节点或者删除节点时,数据迁移量最少?——一致性哈希算法诞生。

PS:关于一致性哈希算法,我会另外写一篇博客进行详细介绍,这里只是大概介绍一下。

  假设有一个哈希环,从0到2的32次方,均匀的分成三份,中间存放三个节点,沿着顺时针旋转,从Node1到Node2之间的数据,存放在Node2节点上;从Node2到Node3之间的数据,存放在Node3节点上,依次类推。

假设Node1节点宕机,那么原来Node3到Node1之间的数据这时候改为存放到Node2节点上,Node2到Node3之间数据保持不变,原来Node1到Node2之间的数据还是存放在Node2上,也就是只影响三分之一的数据,节点越多,影响数据越少。

  同理,假设增加一个节点,影响的数据甚至更少。

  当然,实际业务中并不是你节点均匀分布,访问就会很平均,这时候容易造成访问倾斜的问题,这里就会引出虚拟节点的定义。我这里就不做详解了。

4、Redis Cluster虚拟槽分区

Redis集群数据分布没有使用一致性哈希分布,而是使用虚拟槽分区概念。

Redis内部内置了序号 0-16383 个槽位,每个槽位可以用来存储一个数据集合,将这些槽位按顺序分配到集群中的各个节点。每次新的数据到来,会通过哈希函数 CRC16(key) 算出将要存储的槽位下标,然后通过该下标找到前面分配的Redis节点,最后将数据存储到该节点中。

具体情况如下图:(以集群有3个节点为例)

  至于为什么Redis不使用一致性哈希分布,而是虚拟槽分区。因为虚拟槽分区虽然没有一致性哈希那么灵活,但是CRC16(key)%16384 已经分布很均匀了,并且对于后面节点增删(按照序号)操作起来也很方便。

5、原生搭建 Redis Cluster

集群以三主三从的模式来搭建。

①、服务器列表

②、配置各个节点参数

#配置端口
port?${port}
#以守护进程模式启动
daemonize?yes
#pid的存放文件
pidfile?/var/run/redis_${port}.pid
#日志文件名
logfile?"redis_${port}.log"
#存放备份文件以及日志等文件的目录
dir?"/opt/redis/data"??
#rdb备份文件名
dbfilename?"dump_${port}.rdb"
#开启集群功能
cluster-enabled?yes
#集群配置文件,节点自动维护
cluster-config-file?nodes-${port}.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage?no

配置完成后,通过 redis-server redis.conf 命令启动这六个节点。

启动之后,进程后面会有 cluster 的字样:

③、建立各个节点通信   这里有 6 个节点,我们只需要拉通 1 个节点和另外 5 个节点之间通信,那么每两个节点就能够通信了。命令如下:

redis-cli -h -p {password} cluster meet {port2}

这里的 -a 参数表示该Redis节点有密码,如果没有可以不用加此参数。

实例中的 6 个节点,分别进行如下命令:

redis-cli?-p?6379?-a?123?cluster?meet?192.168.14.101?6382
redis-cli?-p?6379?-a?123?cluster?meet?192.168.14.102?6380
redis-cli?-p?6379?-a?123?cluster?meet?192.168.14.102?6383
redis-cli?-p?6379?-a?123?cluster?meet?192.168.14.103?6381
redis-cli?-p?6379?-a?123?cluster?meet?192.168.14.103?6384

执行完毕后,可以查看节点通信信息:

redis-cli -p 6379 -a 123 cluster nodes

结果如下:

 或者执行如下命令:

redis-cli -p 6379 -a 123 cluster info

结果如下:

④、分配槽位   由于我们是三主三从的架构,所以只需要对主服务器分配槽位即可。三个节点,分配序号为 0-16383 ,总共16384 个槽位。

Node1:0~5460
Node2:5461~10922
Node3:10923~16383

分配槽位的命令如下:

redis-cli -p {password} cluster addslots {{endSlot}}

比如,对于Node1主节点,我们执行命令如下:

redis-cli -p 6379 -a 123 cluster addslots {0..5462}

另外两个节点对于上面的命令更改一下槽位数,然后查看集群信息:

  查看Node1节点信息:

⑤、主从配置   命令如下:

redis-cli -p {nodeId}

前面的${port} 表示从节点的端口,这里的nodeId表示主节点的nodeId,如下:

  如果弄反了,会报如下错误:

(error) ERR To set a master the node must be empty and without assigned slots.

执行三条命令完毕后,查看节点信息:

  这时候,集群状态是成功了。

⑥、测试   经过如上几步操作,集群搭建成功,我们通过如下命令进入客户端:

redis-cli -c -p ${port} -a {password}

注意:必须要加 -c 参数,否则进行键值对操作时会报如下错误:

 正确进入后,可以正确存值和取值。

6、脚本搭建Redis Cluster

上面原生命令安装Redis Cluster 走下来其实挺费劲的,在实际生产环境中,如果集群数量比较大,操作还是容易出错的。

不过Redis官方提供了一个安装集群的脚本,在Redis安装目录的src目录下——redis-trib.rb,使用该脚本可以快速搭建Redis Cluster集群。

注意:redis版本在5之前的集群运行该脚本需要安装ruby环境,而redis5.0之后已经将redis-trib.rb 脚本的功能全部集成到redis-cli之中了,所以如果当前版本是Redis5,那么可以不用安装ruby环境。

下面我分别介绍这两种方法。

①、Redis5之前使用redis-trib.rb脚本搭建   redis-trib.rb脚本使用ruby语言编写,所以想要运行次脚本,我们必须安装Ruby环境。安装命令如下:

yum?-y?install?centos-release-scl-rh
yum?-y?install?rh-ruby23??
scl?enable?rh-ruby23?bash
gem?install?redis

安装完成后,我们可以使用 ruby -v 查看版本信息。

  Ruby环境安装完成后。运行如下命令:

redis-trib.rb create --replicas 1 192.168.14.101:6379 192.168.14.102:6380 192.168.14.103:6381 192.168.14.101:6382 192.168.14.102:6383 192.168.14.103:6384

关于这个命令的解释下面会一起介绍。

②、Redis5版本集群搭建    前面我们就说过,redis5.0之后已经将redis-trib.rb 脚本的功能全部集成到redis-cli中了,所以我们直接使用如下命令即可:

redis-cli -a ${password} --cluster create 192.168.14.101:6379 192.168.14.102:6380 192.168.14.103:6381 192.168.14.101:6382 192.168.14.102:6383 192.168.14.103:6384 --cluster-replicas 1

①、${password} 表示连接Redis的密码,通常整个集群我们要么不设置密码,要么设置成一样的。

②、后面的六个ip:port,按照顺序,前面三个是主节点,后面三个是从节点,顺序不能错。

③、最后数字 1 表示一个主节点只有一个从节点。和前面的配置相对应。

7、集群扩容

这里新增两个端口分别是 6390、6391的节点。其中6391节点是6390节点的从节点。

①、配置新增节点文件   比如,我们将6379节点的配置文件redis.conf 拷贝两份,然后将里面的配置文件里面的字符串 6379 分别替换成 6390 和 6391。

:%s/6379/6390/g,:%s/6379/6391/g

替换完成之后,分别启动这两个节点。

这时候这两个节点都不在集群当中,是两个孤儿节点。

②、将新增主节点加入到集群中   命令如下:

redis-cli -p existing_port -a ${password} --cluster add-node new_host:new_port existing_host:existing_port

我这里是将新增的主节点 6390 添加到原来的集群中。

redis-cli -p 6379 -a 123 --cluster add-node 192.168.14.101:6390 192.168.14.101:6379

添加完毕后,这时候查看集群状态

  6390节点已经存在集群中了,但是还没有分配槽位。

③、为新增主节点分配槽位   分配命令如下

redis-cli -p existing_port -a ${password} --cluster reshard existing_host:existing_port

后面的
existing_host:existing_port表示原来集群中的任意一个节点,这个命令表示将源节点的一部分槽位分配个新增的节点。

在分配过程中,会出现如下几个提示:

#后面的2000表示分配2000个槽位给新增节点
How?many?slots?do?you?want?to?move?(from?1?to?16384)??2000
#表示接受节点的NodeId,填新增节点6390的
What?is?the?receiving?node?ID??64a0779c7baef78c8fd0f2bb6e73f29375e00133d
#这里填槽的来源,要么填all,表示所有master节点都拿出一部分槽位分配给新增节点;
#要么填某个原有NodeId,表示这个节点拿出一部分槽位给新增节点
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:?all

分配成功后,我们查看节点信息:

  我们发现已经给该节点分配了槽位。

④、将新增的从节点添加到集群中

redis-cli -p 6379 -a 123 --cluster add-node 192.168.14.101:6391 192.168.14.101:6379

⑤、建立新增节点的主从关系   命令如下:

redis-cli -p {nodeId}

前面的${port} 表示从节点的端口,这里的nodeId表示主节点的nodeId。

⑥、测试   查看节点信息,发现4主4从。

  在6379节点新增一个字符串 (k4,v4),然后到6390节点查看:

  自此,大功告成。

8、集群收缩

这里我们将上一步添加的主从节点6390和6391从集群中移除。

①、迁移待移除节点的槽位   移除之前的节点信息:

redis-cli -p existing_port -a {Redis登录密码} --cluster reshard --cluster-from {待移除的NodeId} --cluster-to {接受移除节点的NodeId} --cluster-slots {移除的槽位个数}
existing_host:existing_port

比如,我这里要移除主节点 6390 的所有槽位,给6379节点。

redis-cli -p 6379 -a 123 --cluster reshard --cluster-from 4a0779c7baef78c8fd0f2bb6e73f29375e00133d --cluster-to 001a22b1edae6ea1699b753d193871824723f375 --cluster-slots 2000 192.168.14.101:6379

移除完后,查看节点信息,发现6379已经没有槽位了。

②、移除待删除主从节点   注意:要首先移除从节点,然后再移除主节点,因为如果你先移除主节点,会触发集群的故障转移。

所以,我们应该先移除 6391 从节点,然后在移除 6390 主节点。移除命令如下:

redis-cli -p existing_port -a {Redis登录密码} --cluster del-node host:port {待删除的NodeId}

删除 6391 从节点:

redis-cli -p 6379 -a 123 --cluster del-node 192.168.14.101:6379 3622ec34956b624358722e6f4a2b762574d35bf0

删除 6390 主节点:

redis-cli -p 6379 -a 123 --cluster del-node 192.168.14.101:6379 4a0779c7baef78c8fd0f2bb6e73f29375e00133d

本系列教程持续更新,可以微信搜索「 IT可乐 」第一时间阅读。回复《电子书》有我为大家特别筛选的书籍资料

相关推荐

redis的八种使用场景

前言:redis是我们工作开发中,经常要打交道的,下面对redis的使用场景做总结介绍也是对redis举报的功能做梳理。缓存Redis最常见的用途是作为缓存,用于加速应用程序的响应速度。...

基于Redis的3种分布式ID生成策略

在分布式系统设计中,全局唯一ID是一个基础而关键的组件。随着业务规模扩大和系统架构向微服务演进,传统的单机自增ID已无法满足需求。高并发、高可用的分布式ID生成方案成为构建可靠分布式系统的必要条件。R...

基于OpenWrt系统路由器的模式切换与网页设计

摘要:目前商用WiFi路由器已应用到多个领域,商家通过给用户提供一个稳定免费WiFi热点达到吸引客户、提升服务的目标。传统路由器自带的Luci界面提供了工厂模式的Web界面,用户可通过该界面配置路...

这篇文章教你看明白 nginx-ingress 控制器

主机nginx一般nginx做主机反向代理(网关)有以下配置...

如何用redis实现注册中心

一句话总结使用Redis实现注册中心:服务注册...

爱可可老师24小时热门分享(2020.5.10)

No1.看自己以前写的代码是种什么体验?No2.DooM-chip!国外网友SylvainLefebvre自制的无CPU、无操作码、无指令计数器...No3.我认为CS学位可以更好,如...

Apportable:拯救程序员,IOS一秒变安卓

摘要:还在为了跨平台使用cocos2d-x吗,拯救objc程序员的奇葩来了,ApportableSDK:FreeAndroidsupportforcocos2d-iPhone。App...

JAVA实现超买超卖方案汇总,那个最适合你,一篇文章彻底讲透

以下是几种Java实现超买超卖问题的核心解决方案及代码示例,针对高并发场景下的库存扣减问题:方案一:Redis原子操作+Lua脚本(推荐)//使用Redis+Lua保证原子性publicbo...

3月26日更新 快速施法自动施法可独立设置

2016年3月26日DOTA2有一个79.6MB的更新主要是针对自动施法和快速施法的调整本来内容不多不少朋友都有自动施法和快速施法的困扰英文更新日志一些视觉BUG修复就不翻译了主要翻译自动施...

Redis 是如何提供服务的

在刚刚接触Redis的时候,最想要知道的是一个’setnameJhon’命令到达Redis服务器的时候,它是如何返回’OK’的?里面命令处理的流程如何,具体细节怎么样?你一定有问过自己...

lua _G、_VERSION使用

到这里我们已经把lua基础库中的函数介绍完了,除了函数外基础库中还有两个常量,一个是_G,另一个是_VERSION。_G是基础库本身,指向自己,这个变量很有意思,可以无限引用自己,最后得到的还是自己,...

China's top diplomat to chair third China-Pacific Island countries foreign ministers' meeting

BEIJING,May21(Xinhua)--ChineseForeignMinisterWangYi,alsoamemberofthePoliticalBureau...

移动工作交流工具Lua推出Insights数据分析产品

Lua是一个适用于各种职业人士的移动交流平台,它在今天推出了一项叫做Insights的全新功能。Insights是一个数据平台,客户可以在上面实时看到员工之间的交流情况,并分析这些情况对公司发展的影响...

Redis 7新武器:用Redis Stack实现向量搜索的极限压测

当传统关系型数据库还在为向量相似度搜索的性能挣扎时,Redis7的RedisStack...

Nginx/OpenResty详解,Nginx Lua编程,重定向与内部子请求

重定向与内部子请求Nginx的rewrite指令不仅可以在Nginx内部的server、location之间进行跳转,还可以进行外部链接的重定向。通过ngx_lua模块的Lua函数除了能实现Nginx...