前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis各种模式部署及工作原理-单节点、主从复制、redis-sentinel(哨兵)以及redis-cluster(集群)

Redis各种模式部署及工作原理-单节点、主从复制、redis-sentinel(哨兵)以及redis-cluster(集群)

作者头像
行百里er
发布2020-12-02 15:34:37
1.9K0
发布2020-12-02 15:34:37
举报
文章被收录于专栏:JavaJourneyJavaJourney

工欲善其事,必先利其器。

要用好Redis这把利剑,先得把Redis环境摸透,今天就和大家一起玩一下Redis的部署方案。

Redis的部署方案:

  • 单节点单例部署
  • Replication 主从复制模式
  • Redis Sentinel 哨兵
  • Redis Cluster 集群

开始之前

准备以及确认一下操作系统版本,所需软件版本。

操作系统:

虚拟机 CentOS,版本为 CentOS 7.6,4 CPUs

Redis:

本次安装最新的稳定版本「6.0.8」

❝Redis 6.0 引入了SSL,新的RESP3协议,acl,客户端缓存,无磁盘复制,I/O线程,更快的RDB加载,新的模块api和更多的改进。 ❞

Redis单节点部署

这种方式部署很简单,就是安装一个软件,配置好相关配置项,然后启动它就可以了。

这里我提供一下详细的安装步骤,后面弄主从复制、哨兵和集群都复用这种方式安装(面向CV安装^ _ ^)。

主机规划

单节点好弄,安装一台虚拟机,设置好IP地址即可。

主机名称

IP地址

端口

Redis-Standalone

192.168.2.11

6379

虚拟机设置

从模板机克隆一台虚拟机,并设置主机名称和ip地址。

❝安装虚拟机可参考:手摸手助你搭建etcd集群 中的「VMware安装CentOS7模板机」部分。 ❞

设置主机名
代码语言:javascript
复制
hostnamectl set-hostname redis-standalone
设置IP地址
代码语言:javascript
复制
vim /etc/sysconfig/network-scripts/ifcfg-ens33

# 将IPADDR修改为192.168.2.11
IPADDR=192.168.2.11

部署Redis

下载、解压、安装
代码语言:javascript
复制
# 下载
wget https://download.redis.io/releases/redis-6.0.8.tar.gz

# 解压
tar -zxf redis-6.0.8.tar.gz

# 安装
mkdir -p /usr/local/redis
cd redis-6.0.8
make && make install PREFIX=/usr/local/redis

然而make的时候出现了错误:

代码语言:javascript
复制
 ^
make[1]: *** [server.o] Error 1
make[1]: Leaving directory `/root/redis-6.0.8/src'
make: *** [all] Error 2

别慌,看一下gcc版本:

升级一下gcc先:

代码语言:javascript
复制
# 依次执行如下命令
yum -y install centos-release-scl
 
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
 
scl enable devtoolset-9 bash
 
echo "source /opt/rh/devtoolset-9/enable" >> /etc/profile
 
gcc -v

再来执行安装:

代码语言:javascript
复制
make clean
make
make install PREFIX=/usr/local/redis

安装成功

配置环境变量
代码语言:javascript
复制
vi /etc/profile

末尾添加:
export REDIS_HOME=/usr/local/redis
export PATH=$PATH:$REDIS_HOME/bin

使之生效:
source /etc/profile
使用自带脚本utils/install_server.sh安装Redis服务
代码语言:javascript
复制
cd utils

# 可执行多次,每执行一次可生成一个redis实例以及配置文件
./install_server.sh 

这里遇到了一个坑:CentOS 7 ,redis 6 执行install_server.sh遇到如下问题:

代码语言:javascript
复制
[root@redis-standalone redis-6.0.8]# cd utils/
[root@redis-standalone utils]# ./install_server.sh 
Welcome to the redis service installer
This script will help you easily set up a running redis server

This systems seems to use systemd.
Please take a look at the provided example service unit files in this directory, and adapt and install them. Sorry!

解决方案:

代码语言:javascript
复制
vi install_server.sh

注释下面的代码即可
#bail if this system is managed by systemd
#_pid_1_exe="$(readlink -f /proc/1/exe)"
#if [ "${_pid_1_exe##*/}" = systemd ]
#then
#       echo "This systems seems to use systemd."
#       echo "Please take a look at the provided example service unit files in this directory, and adapt and install them. Sorry!"
#       exit 1
#fi

再执行:

install_server.sh安装过程

安装成功:

代码语言:javascript
复制
[root@redis-standalone utils]# ps -ef|grep redis
root      12655      1  0 16:51 ?        00:00:00 /usr/local/redis/bin/redis-server 127.0.0.1:6379
root      12663  11520  0 16:55 pts/0    00:00:00 grep --color=auto redis
[root@redis-standalone utils]# redis-cli 
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> 

修改一下配置,install_server.sh已经帮我们自动生成了配置文件,配置文件位于/etc/redis/6379.conf

如果其他客户端需要连接Redis服务,比如Redisson客户端连接,需要做一些配置:

代码语言:javascript
复制
# 注释掉下面这一行
bind 127.0.0.1

# 自己的Redis密码
# requirepass foobared
requirepass redis123

保存,重启Redis并验证:

代码语言:javascript
复制
[root@redis-standalone ~]# service redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...
[root@redis-standalone ~]# ps -ef|grep redis
root      12713      1  0 17:14 ?        00:00:00 /usr/local/redis/bin/redis-server *:6379
root      12719  11520  0 17:14 pts/0    00:00:00 grep --color=auto redis
[root@redis-standalone ~]# redis-cli 
127.0.0.1:6379> keys *
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth redis123
OK
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> 

这样,单节点的Redis就部署好了。

Redis主从复制

单节点的Redis服务我们支起来了,但是实际应用中,单节点的问题会会很明显:「数据备份」问题和数据体量较大时的「性能问题」

Redis已经为我们提供了解决方案,就是Redis主从模式。

主从模式指的是使用一个Redis实例作为主机,其余的实例作为备份机。

主机和从机的数据完全一致,「主机支持数据的写入和读取」等各项操作,而「从机则只支持与主机数据的同步和读取」,也就是说,客户端可以将数据写入到主机,「由主机自动将数据的写入操作同步到从机」

主从模式很好的解决了数据备份问题,并且由于主从服务数据几乎是一致的,因而可以「将写入数据的命令发送给主机执行」,而「读取数据的命令发送给不同的从机执行」,从而达到「读写分离」的目的。

Redis的主从复制机制

  1. 当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave :包括客户端的写入、key 的过期或被逐出等等。
  2. 当 master 和 slave 之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。
  3. 当无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave 。

搭建Redis主从复制环境

BB了这么多,下面来搭建一下Redis主从复制模式环境。

主从模式的配置主要的配置点有两个:

  • 当前实例端口号
  • 当前实例是主机还是从机,是从机的话其主机的ip和端口是什么
主机规划

本次搭建「1主3从」的主从复制环境,主机规划如下:

主机名称

角色

IP地址

端口

Redis-Master-01

Master

192.168.2.20

9736

Redis-Slave-02

Slave

192.168.2.21

9736

Redis-Slave-03

Slave

192.168.2.22

9736

Redis-Slave-04

Slave

192.168.2.23

9736

准备四台安装好Redis的主机

按照单节点部署的方式先创建四台虚拟机,并且安装好Redis。

根据主机规划,设置主机名称和IP地址:

代码语言:javascript
复制
# 依次设置4台主机的名称
hostnamectl set-hostname Redis-Master-01
hostnamectl set-hostname Redis-Slave-02
hostnamectl set-hostname Redis-Slave-03
hostnamectl set-hostname Redis-Slave-04

# 4台主机分别执行
vim /etc/sysconfig/network-scripts/ifcfg-ens33

# 修改其中的IPADDR
IPADDR=xx

按照Redis单节点安装的方式如法炮制,在四台机器上安装,

好了,安装完了:

主从模式配置
  1. Redis-Master-01 节点配置
代码语言:javascript
复制
vim /etc/redis/9736.conf

# 修改一下IP地址
bind 192.168.2.20
  1. Redis-Slave-02
代码语言:javascript
复制
vim /etc/redis/9736.conf

# 1. 修改一下IP地址
bind 192.168.2.21

# 2. 定义从节点,追随主节点
# replicaof <masterip> <masterport>
replicaof 192.168.2.20 9736
  1. Redis-Slave-03
代码语言:javascript
复制
vim /etc/redis/9736.conf

# 1. 修改一下IP地址
bind 192.168.2.22

# 2. 定义从节点,追随主节点
# replicaof <masterip> <masterport>
replicaof 192.168.2.20 9736
  1. Redis-Slave-04
代码语言:javascript
复制
vim /etc/redis/9736.conf

# 1. 修改一下IP地址
bind 192.168.2.23

# 2. 定义从节点,追随主节点
# replicaof <masterip> <masterport>
replicaof 192.168.2.20 9736
启动
  1. 启动主节点
代码语言:javascript
复制
service redis_9736 restart
  1. 启动从节点

三台从节点均执行:

代码语言:javascript
复制
redis-server /etc/redis/9736.conf
验证

主节点上:

代码语言:javascript
复制
redis-cli -h 192.168.2.20 -p 9736
代码语言:javascript
复制
192.168.2.20:9736> set name xiaoming
OK
192.168.2.20:9736> get name
"xiaoming"
192.168.2.20:9736> info replication
# Replication
role:master
connected_slaves:3
slave0:ip=192.168.2.21,port=9736,state=online,offset=1502,lag=1
slave1:ip=192.168.2.22,port=9736,state=online,offset=1502,lag=0
slave2:ip=192.168.2.23,port=9736,state=online,offset=1502,lag=1
master_replid:43cc1e16a95d3d1bf6a0e1657576da2b8d6ea9ed
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1502
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1502

从节点:

代码语言:javascript
复制
[root@redis-slave-04 ~]# redis-cli -h 192.168.2.23 -p 9736
192.168.2.23:9736> get name
"xiaoming"
192.168.2.23:9736> info replication
# Replication
role:slave
master_host:192.168.2.20
master_port:9736
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:1488
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:43cc1e16a95d3d1bf6a0e1657576da2b8d6ea9ed
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1488
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:57
repl_backlog_histlen:1432

OK!

Redis Sentinel 哨兵

Redis主从模式解决了数据备份和单例可能存在的性能问题,但是其也引入了新的问题。

前面我们主从模式配置了1主3从4个Redis实例,并且每个实例都使用不同的ip,根据前面所述,主从模式下可以「将读写操作分配给不同的实例进行」从而达到提高系统吞吐量的目的,但也正是因为这种方式造成了使用上的不便。

停掉master:

在slave上进行操作:

因为「每个客户端连接Redis实例的时候都是指定了ip和端口号」的,「如果所连接的Redis实例因为故障下线了,而主从模式也没有提供一定的手段通知客户端另外可连接的客户端地址,因而需要手动更改客户端配置重新连接」

另外,主从模式下,如果主节点由于故障下线了,那么从节点因为没有主节点而同步中断,因而「需要人工进行故障转移工作」

Redis Sentinel架构提供了解决方案。

Sentinel是哨兵的意思,Redis Sentinel,顾名思义,Redis的哨兵,也就是监控的意思。

Redis Sentinel为Redis提供「高可用性」。在实践中,这意味着使用Sentinel你可以创建一个Redis部署,在「没有人为干预的情况下抵抗某些类型的故障」-自动转移故障。

Redis Sentinel还提供其他附带任务,如监控、通知,并充当客户端的配置提供者。

  • 「监控(Monitoring)」:Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 「提醒(Notification)」:当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
  • 「自动故障迁移(Automatic failover)」:如果一个主服务器不能正常工作,哨兵可以启动一个故障转移过程,其中一个副本被提升为主服务器,其他额外的副本被重新配置为使用新的主服务器,并且使用Redis服务器的应用程序被告知在连接时使用的新地址。
  • 「配置中心(Configuration provider)」:哨兵充当客户端服务发现:客户端连接到哨兵,以询问负责给定服务的当前Redis主服务器的地址。如果发生故障转移,哨兵将报告新地址。

搭建Redis Sentinel环境

主机规划

Redis Sentinel体系中的几个角色概念:

  • master节点

❝Redis主服务,一个独立的Redis进程。 ❞

  • slave(replica)节点

❝Redis从服务,一个独立的Redis进程。 ❞

  • sentinel节点

❝监控Redis数据节点,一个独立的Sentinel进程。 ❞

  • sentinel节点集合

❝若干个Sentinel节点的抽象集合,若干Sentinel节点进程。 ❞

Redis Sentinel架构

主从模式根据前文已经搭建起来了,现在再来整三台Sentinel主机。

主机名称

角色

IP地址

端口

Redis-Master-01

Master

192.168.2.20

9736

Redis-Slave-02

Slave

192.168.2.21

9736

Redis-Slave-03

Slave

192.168.2.22

9736

Redis-Slave-04

Slave

192.168.2.23

9736

Redis-Sentinel-05

Sentinel

192.168.2.31

29736

Redis-Sentinel-06

Sentinel

192.168.2.32

29736

Redis-Sentinel-07

Sentinel

192.168.2.33

29736

到目前我们的Redis主机架构初具规模,已经有7台主机了。

❝其实我的渣电脑已经不堪重负了,不得已将这7台虚拟机的内存都调到1G了,是时候加内存了... ❞

配置Sentinel

分别在三台Redis Sentinel虚拟机上安装Redis,安装好后(可以不用执行utils/install_server.sh)按如下步骤进行配置:

❝可以拷贝Redis解压目录下的sentinel.conf,里面有很详细的注释,这里为了看得清楚配置,直接创建sentinel配置文件。 ❞

  1. mkdir /etc/redis
  2. cd /etc/redis
  3. vim sentinel-29736.conf
代码语言:javascript
复制
sentinel monitor mymaster 192.168.2.20 9736 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
启动Sentinel

由于我们配置了Redis环境变量 (/etc/profile),所以可以直接使用Redis的命令。

代码语言:javascript
复制
[root@redis-sentinel-05 ~]# redis-sentinel /etc/redis/sentinel-29736.conf

启动信息:

看一下配置文件,帮我们自动生成了一些信息:

这样启动是前台启动,我们再来修改一下配置文件,让它后台启动,然后在bind一下ip地址,让sentinel之间可以互相通信。

最终的配置文件长这样:

代码语言:javascript
复制
bind 192.168.2.30
port 29736
daemonize yes
sentinel monitor mymaster 192.168.2.20 9736 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

❝bind的ip地址是各自sentinel的ip地址。 ❞

再次启动三台Sentinel:

代码语言:javascript
复制
[root@redis-sentinel-05 ~]# redis-sentinel /etc/redis/sentinel-29736.conf
[root@redis-sentinel-05 ~]# ps -ef|grep redis
root      12006      1  1 12:02 ?        00:00:00 redis-sentinel 192.168.2.30:29736 [sentinel]
root      12012   7129  0 12:02 pts/0    00:00:00 grep --color=auto redis
[root@redis-sentinel-05 ~]# redis-cli -h 192.168.2.30 -p 29736
192.168.2.30:29736> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.2.20:9736,slaves=3,sentinels=3
192.168.2.30:29736> 

由此可见,Sentinel检测到主从节点总共有4个,其中1个主节点,3个从节点,并且Sentinel节点总共也有3个。

验证Sentinel自动故障转移

启动完成之后,我们kill掉主节点Redis来模拟Sentinel的故障转移过程。

首先,在Redis Master上看一下主从节点信息:

代码语言:javascript
复制
192.168.2.20:9736> info replication
# Replication
role:master
connected_slaves:3
slave0:ip=192.168.2.22,port=9736,state=online,offset=123655,lag=1
slave1:ip=192.168.2.23,port=9736,state=online,offset=123655,lag=1
slave2:ip=192.168.2.21,port=9736,state=online,offset=123655,lag=1
master_replid:129a7ea8e6bc55feac36fd6c1622cfc37c33772f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:123933
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:123933
192.168.2.20:9736> 

Redis Slave:

代码语言:javascript
复制
192.168.2.21:9736> info replication
# Replication
role:slave
master_host:192.168.2.20
master_port:9736
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:144645
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:129a7ea8e6bc55feac36fd6c1622cfc37c33772f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:144645
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:855
repl_backlog_histlen:143791
192.168.2.21:9736> 

然后我们停掉主节点,在master上执行:

代码语言:javascript
复制
192.168.2.20:9736> SHUTDOWN SAVE

此时主节点出故障了,再在从节点执行一下info replication

节点192.168.2.21:

代码语言:javascript
复制
192.168.2.21:9736> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.2.22,port=9736,state=online,offset=175027,lag=1
slave1:ip=192.168.2.23,port=9736,state=online,offset=175027,lag=1
master_replid:617929ec5bd1fa6c072a62cc07d3e4ad149a1b82
master_replid2:129a7ea8e6bc55feac36fd6c1622cfc37c33772f
master_repl_offset:175027
second_repl_offset:174032
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:855
repl_backlog_histlen:174173

节点192.168.2.22:

代码语言:javascript
复制
192.168.2.22:9736> info replication
# Replication
role:slave
master_host:192.168.2.21
master_port:9736
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:180059
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:617929ec5bd1fa6c072a62cc07d3e4ad149a1b82
master_replid2:129a7ea8e6bc55feac36fd6c1622cfc37c33772f
master_repl_offset:180059
second_repl_offset:174032
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:180059

节点192.168.2.23:

代码语言:javascript
复制
192.168.2.23:9736> info replication
# Replication
role:slave
master_host:192.168.2.21
master_port:9736
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:186356
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:617929ec5bd1fa6c072a62cc07d3e4ad149a1b82
master_replid2:129a7ea8e6bc55feac36fd6c1622cfc37c33772f
master_repl_offset:186356
second_repl_offset:174032
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:29
repl_backlog_histlen:186328

如你所见,「192.168.2.21」的Redis变成了master,并且slave有两个,分别是「192.168.2.22」「192.168.2.23」!也就是说新的主从Redis不和原来的master 「192.168.2.20」 玩了,它被踢出局了!

然后此时它胡汉三(「192.168.2.20」)又回来了,Redis重新上线:

再次如你所见,「192.168.2.20」的Redis重新启动后,Sentinel节点检测到其重新连接,那么对其发送命令,使其成为新的主节点的「从节点」

Sentinel故障转移原理

「Redis主节点 192.168.2.20」(以下简称「20」,下面的IP地址均如此简称)因故障下线,Redis Sentinel进行故障转移的过程:

  1. 某个Sentinel节点(假设是「30」这个Sentinel节点)发送监测消息给「20」,如果在指定时间内收不到回复,该Sentinel认为「20」主节点已经下线
  2. 「30」这个Sentinel节点发消息给「31/32」这两个Sentinel,询问他们是否认为 「20 master」 已经下线
  3. 「31/32」这两个哨兵收到消息后也会监测「20」 Redis主节点,如果它也认为master下线,则回复「30」 Sentinel节点(就是第2步中的询问者):“我也认为master已经下线”
  4. 「30」节点最先收到超过2(配置文件中配置的数目和当前Sentinel节点集合数的一半,这里两个数目的较大值)的Sentinel节点回复说当前主节点已下线,那么其就会「对主节点进行故障转移工作」
  5. 向某个从节点(前面的实验选中的从节点为「192.168.2.21」)发送 replicaof no one,使其成为新的主节点
  6. Sentinel哨兵向其余「22/23」节点发送replicaof 192.168.2.21 9736命令,使「22/23」两个Redis节点成为「21」的从节点
  7. Sentinel选出新的master之后,仍然会继续监控之前下线的「20」节点,如果其重新上线,那么Sentinel哨兵向其发送replicaof 192.168.2.21 9736命令,也成为了新主节点的从节点

如此,故障转移工作完成。

Redis Cluster 集群

Redis主从复制解决了单节点的容量问题,Redis Sentinel哨兵解决了故障转移以及主节点下线客户端无法识别新的可用节点的问题,但是如果是从节点下线了,Sentinel是不会对其进行故障转移的,并且连接从节点的客户端也无法获取到新的可用从节点。

Redis集群能够有效的解决这一问题。

从另一方面来看,当遇到单机内存、并发和流量瓶颈等问题时,可采用Cluster方案达到负载均衡的目的。

Redis集群原理

Redis集群中数据是和槽(slot)挂钩的。

其总共定义了「16384」个槽,所有的数据根据「一致性哈希算法」会被映射到这16384个槽中的某个槽中;

另一方面,这16384个槽是按照设置被分配到不同的Redis节点上的,比如启动了三个Redis实例:Redis-A,Redis-B和Redis-C,这里将0-5460号槽分配给Redis-A,将5461-10922号槽分配给Redis-B,将10923-16383号槽分配给Redis-C(总共有16384个槽,但是其标号类似数组下标,是「从0到16383」)。

也就是说「数据的存储只和槽有关,并且槽的数量是一定的」,由于一致性Hash算法是一定的,因而将这16384个槽分配给无论多少个Redis实例,「对于确认的数据其都将被分配到确定的槽位上」

Redis集群通过这种方式来达到Redis的高效和高可用性目的。

❝一致哈希算法根据数据的key值计算映射位置时和所使用的节点数量有非常大的关系。 一致哈希分区的实现思路是为系统中每个节点分配一个token,范围一般在0~2^32,这些token构成一个「哈希环」,数据读写执行节点查找操作时,先根据key计算hash值,然后「顺时针找到第一个大于等于该hash值的token节点」,需要操作的数据就保存在该节点上。 ❞

一致哈希分区存在如下问题:

  • 加减节点会造成哈希环中部分数据无法命中,需要手动处理或忽略这部分数据;
  • 当使用少量节点时,节点变化将大范围影响环中数据映射,因此这种方式不适合少量节点的分布式方案;
  • 普通的一致性哈希分区在增减节点时需要增加一倍或减去一半节点才能保证数据和负载的平衡。

Redis的应对方案是,使用了「虚拟槽」来处理分区时节点变化的问题,也即「将所有的数据映射到16384个虚拟槽位上,当Redis节点变化时数据映射的槽位将不会变化」,并且这也是Redis进行节点扩张的基础。

Redis集群配置

主机规划

❝由于本人电脑太渣,跑不起来太多的虚拟机,现将3主3从的集群放在3台机器上(伪集群,真集群应该是6台),这3台主机每台开两个redis实例来模拟3主3从架构;另外仍然用上面的3台Sentinel做哨兵。 ❞

主机名称

角色

IP地址

端口

Redis-Cluster-01

Master

192.168.2.50

7000

Redis-Cluster-01

Slave

192.168.2.50

7001

Redis-Cluster-02

Master

192.168.2.51

7000

Redis-Cluster-02

Slave

192.168.2.51

7001

Redis-Cluster-03

Master

192.168.2.52

7000

Redis-Cluster-03

Slave

192.168.2.52

7001

Redis-Sentinel-05

Sentinel

192.168.2.31

29736

Redis-Sentinel-06

Sentinel

192.168.2.32

29736

Redis-Sentinel-07

Sentinel

192.168.2.33

29736

3主3从,加3个Sentinel节点,一共9个节点的Redis集群。

集群配置

节点redis-cluster-01中的两个配置文件:/etc/redis/7000.conf、/etc/redis/7001.conf

关键配置:

代码语言:javascript
复制
bind 192.168.2.50
port 7000
cluster-enabled yes
cluster-node-timeout 15000
cluster-config-file "nodes-7000.conf"
daemonize yes
pidfile /var/run/redis_7000.pid
logfile "cluster-7000.log"
dbfilename dump-cluster-7000.rdb
appendfilename "appendonly-cluster-7000.aof"

节点redis-cluster-02和redis-cluster-03如法炮制,修改相应的IP地址和端口号。

配置文件并没有指定主、从以及没有对16384个数据槽位进行分配,用redis-cli创建集群可自动生成主从关系以及槽位分配。

启动集群

先启动6个redis实例:

代码语言:javascript
复制
# 每台主机均执行
redis-server /etc/redis/7000.conf
redis-server /etc/redis/7001.conf

redis-cli命令创建集群:

代码语言:javascript
复制
redis-cli --cluster create 192.168.2.50:7000 192.168.2.51:7000 192.168.2.52:7000 192.168.2.50:7001 192.168.2.51:7001 192.168.2.52:7001 --cluster-replicas 1

该命令将默认使用前三个节点作为Master。

cluster nodes看一下集群节点信息:

代码语言:javascript
复制
[root@redis-cluster-01 ~]# redis-cli -h 192.168.2.50 -p 7000
192.168.2.50:7000> CLUSTER NODES
de6e3ff14d649482c14759941c152e2e82288394 192.168.2.52:7000@17000 master - 0 1603187354667 3 connected 10923-16383
84c9b16130ef63de8af2767317f993f2b8b96fee 192.168.2.52:7001@17001 slave 30394326b2b440910ac5ebe09c22dfbca0160ebc 0 1603187353000 2 connected
0fa3ae8a96c98d01ecf461bd6d20b68b037c923f 192.168.2.50:7000@17000 myself,master - 0 1603187353000 1 connected 0-5460
de5e674394b3a4d0797e9fcccd3c225e88f703e7 192.168.2.51:7001@17001 slave 0fa3ae8a96c98d01ecf461bd6d20b68b037c923f 0 1603187356000 1 connected
30394326b2b440910ac5ebe09c22dfbca0160ebc 192.168.2.51:7000@17000 master - 0 1603187354000 2 connected 5461-10922
ada6e03fb281d1fcb0ebec3298b03e4164aabb13 192.168.2.50:7001@17001 slave de6e3ff14d649482c14759941c152e2e82288394 0 1603187356684 3 connected
192.168.2.50:7000> 

cluster info

代码语言:javascript
复制
192.168.2.50:7000> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:285
cluster_stats_messages_pong_sent:295
cluster_stats_messages_sent:580
cluster_stats_messages_ping_received:290
cluster_stats_messages_pong_received:285
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:580

至此,Redis集群搭建完毕。

❝还可以将三个Redis Sentinel哨兵节点的master修改为集群中的三个节点,修改一下配置信息,多个主节点用逗号隔开即可。 ❞

关注我,知识分享无极限

往期推荐

手摸手助你从零开始搭建etcd集群

还有比Redis更骚的分布式锁的实现方式吗?有,etcd!

用ZooKeeper实现分布式锁

用ZooKeeper实现分布式配置中心

ZooKeeper原理-paxos算法,ZAB协议

分布式高可用的ZooKeeper集群搭建与基本操作

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 行百里er 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开始之前
  • Redis单节点部署
    • 主机规划
      • 虚拟机设置
        • 设置主机名
        • 设置IP地址
      • 部署Redis
        • 下载、解压、安装
        • 配置环境变量
        • 使用自带脚本utils/install_server.sh安装Redis服务
    • Redis主从复制
      • Redis的主从复制机制
        • 搭建Redis主从复制环境
          • 主机规划
          • 准备四台安装好Redis的主机
          • 主从模式配置
          • 启动
          • 验证
      • Redis Sentinel 哨兵
        • 搭建Redis Sentinel环境
          • 主机规划
          • 配置Sentinel
          • 启动Sentinel
          • 验证Sentinel自动故障转移
          • Sentinel故障转移原理
      • Redis Cluster 集群
        • Redis集群原理
          • Redis集群配置
            • 主机规划
            • 集群配置
            • 启动集群
        • 关注我,知识分享无极限
        相关产品与服务
        云数据库 Redis
        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档