1.redis特点
(1)基于内存
(2)可持久化数据
(3)具有丰富的数据结构类型,适应非关系型数据的存储需求
(4)支持绝大多数主流开发语言,如C、C++、Java、Python、R、JavaScript等。
(5)支持集群模式,高效、稳定。
2.数据类型
(1)键值对形式。
(2)Redis的数据结构类型,指的就是Redis值的结构类型。
3. Redis作用
(1)本质是数据库,能存储数据。
Redis能灵活处理非关系型数据的读、写问题,是对MySQL等关系型数据库的补充。新浪微博就是使用Redis集群做数据库
(2)缓存数据。
所谓缓存,就是将数据加载到内存中后直接使用,而不是每次都通过IO流从磁盘上读取。好处:读写效率高。
而Redis则是将数据直接存储在内存中,只有当内存空间不足时,将部分数据持久化到磁盘上。
4.下载安装
# 官网下载
https://redis.io/download
# wget下载方式
wget https://download.redis.io/releases/redis-5.0.14.tar.gz
# cul下载方式
curl -o redis-5.0.14.tar.gz https://download.redis.io/releases/redis-5.0.14.tar.gz
tar xzf redis-5.0.14.tar.gz
mv redis-5.0.14 /usr/local/
cd /usr/local/redis-5.0.14/
# 注意make需要依赖gcc,若未安装使用命令安装:yum install -y gcc
make
# 注意:不需要 make install 编译后可以直接使用
# 若make失败,使用libc模式,使用如下命令重新编译
# make MALLOC=libc
# 修改配置文件 redis.conf 详细参考下面配置文件介绍
vi redis.conf
#显示行号
:set number
# 第69行(注释该行):#bind 127.0.0.1
# 第136行:daemonize yes
# 第507行(打开注释设置密码为123456):requirepass 123456
#开启6379端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
#重新加载防火墙:
firewall-cmd --reload
# redis启动命令
src/redis-server redis.conf
# 内置客户端与 Redis 进行交互
src/redis-cli -p 6379 -a '123456'
redis> set foo bar
redis> get foo
# 关闭命令
src/redis-cli -p 6379 -a '123456' shutdown
Redis内置客户端 redis-cli 命令介绍:
参数说明:
-c:表示以集群方式连接惹redis
-h:指定IP地址
-p:指定端口
-a:指定密码
info replication:查询主从节点信息
info sentinel:查询哨兵sentinel节点信息
cluster nodes:查询集群节点信息
cluster info:查询集群状态信息
5.redis常用配置文件
cat redis.conf | grep -v ^# |grep -v ^$
# 开启这个配置时:redis 只接收来自于该 IP 地址列表的请求,如果不进行设置,那么将处理所有请求。
# bind 127.0.0.1
# 保护模式,默认开启
#1、关闭protected-mode模式 no,此时外部网络可以直接访问
#2、开启protected-mode保护模式 yes,需配置bind ip或者设置访问密码,或者bind ip和密码都设置
protected-mode yes
# redis服务器监听的端口
port 6379
# 默认no,改成yes启用守护进程,redis服务在后台启动
daemonize yes
# 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis_6379.pid文件
pidfile /var/run/redis_6379.pid
# Redis日志输出目录,默认不输出日志到文件。
logfile ""
# 默认有16个数据库
databases 16
# 快照策略
save 900 1
save 300 10
save 60 10000
# 快照文件名,指定数据持久化的文件名
dbfilename dump.rdb
# 快照等持久化文件的存放目录
dir ./
## 设置密码为 123456
requirepass 123456
6.redis持久化
Redis持久化,就是将内存中的数据,永久保存到磁盘上。
Redis持久化有两种方式:RDB(Redis DB)、AOF(AppendOnlyFile)
Redis 可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。RDB 是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis 重启会通过加载dump.rdb文件恢复数据。
6.1 RDB快照模式
# 在默认情况下,Redis 将数据库快照保存在名字为dump.rdb的二进制文件中,可以在redis.conf配置文件中修改持久化信息。
save 900 1 表示在900秒内,至少更新了1条数据。Redis就将数据持久化到硬盘
save 300 10 表示在300内,至少更新了10条数据,Redis就会触发将数据持久化到硬盘
save 60 10000 表示60秒内,至少更新了10000条数据,Redis就会触发将数据持久化到硬盘
6.1.1 策略
1. 自动保存:BGSAVE
按照配置文件中的条件满足就执行BGSAVE;
非阻塞,Redis服务正常接收处理客户端请求;
Redis会folk()一个新的子进程来创建RDB文件,子进程处理完后会向父进程发送一个信号,通知它处理完毕;
父进程用新的dump.rdb替代旧文件。
2.手动保存:SAVE
客户端(redis-cli)发起SAVE命令;
阻塞Redis服务,无法响应客户端请求;
创建新的dump.rdb替代旧文件。
6.1.2 优点
执行效率高;
恢复大数据集速度较AOF快。
6.1.3 缺点
会丢失最近写入、修改的而未能持久化的数据;
folk过程非常耗时,会造成毫秒级不能响应客户端请求。
6.2 AOF模式(追加模式、文本重演)
AOF默认关闭,需要在配置文件中手动开启。
记录所有的写操作命令,在服务启动的时候使用这些命令就可以还原数据库。
Append only file,采用追加的方式保存,默认文件appendonly.aof。
6.2.1 写入机制
AOF机制,添加了一个内存缓冲区(buffer):
将内容写入缓冲区
当缓冲区被填满、或者用户手动执行fsync、或者系统根据指定的写入磁盘策略自动调用fdatasync命令,才将缓冲区里的内容真正写入磁盘里
在缓冲区里的内容未写入磁盘之前,可能会丢失
6.2.2 写入磁盘的策略
appendfsync选项,这个选项的值可以是always、everysec或者no
always:服务器每写入一个命令,就调用一次fdatasync,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,也不会丢失任何已经成功执行的命令数据
everysec(默认):服务器每一秒重调用一次fdatasync,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,最多只丢失一秒钟内的执行的命令数据
no:服务器不主动调用fdatasync,由操作系统决定何时将缓冲区里面的命令写入到硬盘。这种模式下,服务器遭遇意外停机时,丢失命令的数量是不确定的,no 选项并不能给服务器性能带来多大的提升,而且也会增加系统奔溃时数据丢失的数量。
运行速度:always的速度慢,everysec和no都很快
7.Redis主从复制
概念
主从复制模型中,有多个redis节点。
其中,有且仅有一个为主节点Master。从节点Slave可以有多个。
只要网络连接正常,Master会一直将自己的数据更新同步给Slaves,保持主从同步。
特点
(1)主节点Master可读、可写。
(2)从节点Slave只读。(read-only)
因此,主从模型可以提高读的能力,在一定程度上缓解了写的能力。因为能写仍然只有Master节点一个,可以将读的操作全部移交到从节点上,变相提高了写能力。
环境:
系统:centos 7
master(主):192.168.111.202:6380
slave(从):192.168.111.203:6380,6381
#开启防火墙
firewall-cmd --zone=public --add-port=6380/tcp --permanent
firewall-cmd --zone=public --add-port=6381/tcp --permanent
#重新加载防火墙:
firewall-cmd --reload
master 配置文件(192.168.111.202):
cd /usr/local/redis-5.0.14/
mkdir -p 6380
cp -p redis.conf 6380/6380.conf
vi 6380/6380.conf
第69行:bind 127.0.0.1 改为 bind 192.168.111.202
第92行:port 6379 改为 port 6380
第136行:daemonize no 改为 daemonize yes
第158行:pidfile /var/run/redis_6379.pid 改为 pidfile /var/run/redis_6380.pid
第263行:dir ./ 改为 dir /usr/local/redis-5.0.14/6380/
第507行:#requirepass foobared 改为 requirepass 123456
# 其余的参数可以自己去选择性配置
在redis-5.0.14/6380/目录下启动:../src/redis-server 6380.conf
slave 配置(192.168.111.203):
cd /usr/local/redis-5.0.14/
mkdir -p 6380
mkdir -p 6381
cp -p redis.conf 6380/6380.conf
cp -p redis.conf 6381/6381.conf
slave 1 配置(6380.conf)
vi 6380/6380.conf
第69行:bind 192.168.111.203
第92行:port 6380
第136行:daemonize yes
第158行:pidfile /var/run/redis_6380.pid
第263行:dir ./ 改为 dir /usr/local/redis-5.0.14/6380/
第286行(主从复制,填写master的ip和端口):replicaof 192.168.111.202 6380
第293行(填写master的密码):masterauth 123456
第507行:requirepass 123456
# 其余的参数可以自己去选择性配置
在redis-5.0.14/6380/目录下启动:../src/redis-server 6380.conf
slave 2 配置(6381.conf)
vi 6381/6381.conf
第69行:bind 192.168.111.203
第92行:port 6381
第136行:daemonize yes
第158行:pidfile /var/run/redis_6381.pid
第263行:dir ./ 改为 dir /usr/local/redis-5.0.14/6381/
第286行(主从复制,填写master的ip和端口):replicaof 192.168.111.202 6380
第293行(填写master的密码):masterauth 123456
第507行:requirepass 123456
# 其余的参数可以自己去选择性配置
在redis-5.0.14/6381/目录下启动:../src/redis-server 6381.conf
登录master的节点
src/redis-cli -p 6380 -a '123456' -h 192.168.111.202
192.168.111.202:6380> set mytest 321
OK
192.168.111.202:6380> info replication
connected_slaves:2
slave0:ip=192.168.111.203,port=6381,state=online,offset=700,lag=1
slave1:ip=192.168.111.203,port=6380,state=online,offset=700,lag=1
登录slave1的节点
src/redis-cli -p 6380 -a '123456' -h 192.168.111.203
192.168.111.203:6380> get mytest
"321"
192.168.111.203:6380> set test 123
(error) READONLY You can't write against a read only replica. #写操作执行失败提示
登录slave2的节点
src/redis-cli -p 6381 -a '123456' -h 192.168.111.203
192.168.111.203:6380> get mytest
"321"
java连接单机redis测试代码:
<!-- Jedis客户端依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.3.0</version>
</dependency>
package com.util;
import redis.clients.jedis.Jedis;
public class RedisJedisTest {
public static void main(String[] args) {
//创建Jedis实例,连接Redis服务
Jedis jedis = new Jedis("192.168.111.203", 6380);
System.out.println("Redis服务器连接成功!");
// 如果 Redis 服务设置了密码,需要下面这行,没有就不需要
jedis.auth("123456");
//查看服务是否正在运行
System.out.println("服务正在运行:" + jedis.ping());
//存储
// jedis.set("mm", "123");
// jedis.expire("mm", 60);//设置过期时间,秒
// jedis.del("mm");
//获取
String test = jedis.get("mm");
System.out.println(test);
jedis.close();
}
}
redis.conf 详细参数如下:
bind 192.168.111.203 #只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求
protected-mode no #是否开启保护模式,要是配置里没有指定bind和密码。开启该参数后,redis只会本地进行访问,拒绝外部访问
tcp-backlog 511 #此参数确定了TCP连接中已完成队列(完成三次握手之后)的长度
port 6380 #监听的端口号
timeout 0 #此参数为设置客户端空闲超过timeout,服务端会断开连接,为0则服务端不会主动断开连接,不能小于0
tcp-keepalive 300 #间隔多久给对端发送ack,检测挂掉的对端。降低中间设备出问题而导致网络看似连接却已经与对端断开的问题。
daemonize yes #yes:后台运行;no:不是后台运行
supervised no #无监督互动
pidfile /var/run/redis_6380.pid #记录redis的进程号,守护redis的安全
loglevel notice #指定了服务端日志的级别
logfile "" #指定了记录日志的文件。空字符串的话不保留日志
databases 16 #数据库的数量,默认使用的数据库是0。
always-show-logo yes #在启动 redis 时是否 显示 log
save 900 1 #900秒内有1个更改,就将内存中的数据快照写入磁盘。
save 300 10 #300秒内有10个更改,就将内存中的数据快照写入磁盘。
save 60 10000 #60秒内有10000个更改,就将内存中的数据快照写入磁盘。
stop-writes-on-bgsave-error yes #当RDB持久化出现错误后,是否依然进行继续进行工作,yes:不能进行工作,no:可以继续进行工作
rdbcompression yes #配置存储至本地数据库时是否压缩数据
rdbchecksum yes #是否校验rdb文件,会有大概10%的性能损耗
dbfilename dump.rdb #快照,持久化文件,放在dir目录下
dir /usr/local/redis-5.0.14/6380/ #数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录
replicaof 192.168.111.202 6380 # slave复制对应的master,填写主ip和端口
masterauth 123456 #填写master主的密码
replica-serve-stale-data yes #当从库同主机失去连接或者复制正在进行,yes 从库会继续响应客户端的请求,no 从库会返回一个错误
replica-read-only yes #作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)
repl-diskless-sync no # 是否使用socket方式复制数据。disk方式:把rdb文件保存到磁盘,再把磁盘上的rdb文件同时传递给多个slave。socket方式是master,直接把rdb文件以socket的方式发给一次一个slave。
repl-diskless-sync-delay 5 #disk复制的延迟时间
repl-disable-tcp-nodelay no #是否禁止复制tcp链接的tcp nodelay参数,可传递yes或者no。默认是no,即使用tcp nodelay。
replica-priority 100 # 当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举
requirepass 123456 #设置密码
#以下4个表示以非阻塞方式释放内存
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly no #不采用aof方式持久化。是否采用日志的形式来记录每个写操作,并追加到appendonly.aof文件中。默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失。
appendfilename "appendonly.aof" #指定aof持久化方式的文件名,默认值为 appendonly.aof
appendfsync everysec #aof持久化策略每秒执行一次fsync同步
no-appendfsync-on-rewrite no #设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入
auto-aof-rewrite-percentage 100 #当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写
auto-aof-rewrite-min-size 64mb #设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写
aof-load-truncated yes #如果选择的是yes,当截断的aof文件被导入的时候,会自动发布一个log给客户端然后load。如果是no,用户必须手动redis-check-aof修复AOF文件才可以
aof-use-rdb-preamble yes #开启后在对AOF进行重写的时候,AOF文件前半部分是RDB格式,后半部分是AOF格式
lua-time-limit 5000 # 如果达到最大时间限制(毫秒),redis会记个log,然后返回error。当一个脚本超过了最大时限。只有
slowlog-log-slower-than 10000 #慢查询日志记录。执行时间比slowlog-log-slower-than大的请求记录到slowlog里面,单位是微秒,所以1000000就是1秒。
slowlog-max-len 128 #慢查询日志长度。
latency-monitor-threshold 0 #延迟监控功能是关闭
notify-keyspace-events "" #关闭键空间通知使得客户端可以通过订阅频道或模式
hash-max-ziplist-entries 512 # 数据量小于等于hash-max-ziplist-entries的用ziplist,大于hash-max-ziplist-entries用hash
hash-max-ziplist-value 64 # value大小小于等于hash-max-ziplist-value的用ziplist,大于hash-max-ziplist-value用hash
list-max-ziplist-size -2 #-2:最大大小:8kb
list-compress-depth 0 #0:禁用所有列表压缩
set-max-intset-entries 512 # 数据量小于等于set-max-intset-entries用iniset,大于set-max-intset-entries用set
zset-max-ziplist-entries 128 #数据量小于等于zset-max-ziplist-entries用ziplist,大于zset-max-ziplist-entries用zset
zset-max-ziplist-value 64 #value大小小于等于zset-max-ziplist-value用ziplist,大于zset-max-ziplist-value用zset
hll-sparse-max-bytes 3000 #value大小小于等于hll-sparse-max-bytes使用稀疏数据结构(sparse),大于hll-sparse-max-bytes使用稠密的数据结构(dense)
stream-node-max-bytes 4096 #设置限制最大纪录
stream-node-max-entries 100 #设置限制最大输入
activerehashing yes #Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用
client-output-buffer-limit normal 0 0 0 #对于normal client,第一个0表示取消hard limit,第二个0和第三个0表示取消soft limit,normal
client-output-buffer-limit replica 256mb 64mb 60 #如果client-output-buffer一旦超过256mb,又或者超过64mb持续60秒,那么服务器就会立即断开客户端连接
client-output-buffer-limit pubsub 32mb 8mb 60 #如果client-output-buffer一旦超过32mb,又或者超过8mb持续60秒,那么服务器就会立即断开客户端连接
hz 10 #redis执行任务的频率为1s除以hz
dynamic-hz yes ##当启用动态赫兹时,实际配置的赫兹将用作作为基线
aof-rewrite-incremental-fsync yes #如果打开了aof-rewrite-incremental-fsync开关系统会每32MB执行一次fsync。
rdb-save-incremental-fsync yes #在rdb保存的时候,如果打开了rdb-save-incremental-fsync开关,系统会每32MB执行一次fsync。
参考:https://blog.csdn.net/suprezheng/article/details/90679790
8. Redis集群--Sentinel哨兵模式
1.主从模式缺陷
当主节点宕机了,整个集群就没有可写的节点了。
问:由于从节点上备份了主节点的所有数据,那在主节点宕机的情况下,如果能够将从节点变成一个主节点,是不是就可以解决这个问题了呢?
答:是的,这个就是Sentinel哨兵的作用。
2.哨兵的任务
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
(1) 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
(2) 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
(3) 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会进行选举,将其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
3.监控(Monitoring)
(1)Sentinel可以监控任意多个Master和该Master下的Slaves。(即多个主从模式)
(2)同一个哨兵下的、不同主从模型,彼此之间相互独立。
(3)Sentinel会不断检查Master和Slaves是否正常。
4.自动故障切换(Automatic failover)
监控同一个Master的Sentinel会自动连接,组成一个分布式的Sentinel网络,互相通信并交换彼此关于被监视服务器的信息。
疑问:为什么要使用sentinel网络呢?
答:当只有一个sentinel的时候,如果这个sentinel挂掉了,那么就无法实现自动故障切换了。
在sentinel网络中,只要还有一个sentinel活着,就可以实现故障切换。
5.故障切换的过程
(1)投票(半数原则)
当任何一个Sentinel发现被监控的Master下线时,会通知其它的Sentinel开会,投票确定该Master是否下线(半数以上,所以sentinel通常配奇数个)。
(2)选举
当Sentinel确定Master下线后,会在所有的Slaves中,选举一个新的节点,升级成Master节点。
其它Slaves节点,转为该节点的从节点。
(3)原Master重新上线
当原Master节点重新上线后,自动转为当前Master节点的从节点。
8.1哨兵模式部署
使用哨兵模式需要先搭建一个,1主2从,详细配置参考上面。
我这里使用的VMware虚拟机,直接将上面的Slaves 192.168.111.203 再克隆一台 Slaves 192.168.111.204的新的主机并修改bind 192.168.111.204,删除/6380目录下的dump.rdb文件,分别重启3台主机的redis。
master(主):192.168.111.202:6380
slave(从) :192.168.111.203:6380
slave(从) :192.168.111.204:6380
#开启防火墙
firewall-cmd --zone=public --add-port=6380/tcp --permanent
firewall-cmd --zone=public --add-port=26379/tcp --permanent
#重新加载防火墙:
firewall-cmd --reload
在redis-5.0.14/6380/目录下启动:../src/redis-server 6380.conf
登录master的节点
src/redis-cli -p 6380 -a '123456' -h 192.168.111.202
192.168.111.202:6380> info replication
connected_slaves:2
slave0:ip=192.168.111.203,port=6380,state=online,offset=294,lag=1
slave1:ip=192.168.111.204,port=6380,state=online,offset=294,lag=1
3台主机都要启动一个哨兵 sentinel 来监听redis,配置都一样 cd /usr/local/redis-5.0.14/ mkdir -p sentinel cp -p sentinel.conf sentinel/ vi sentinel/sentinel.conf
第21行:port 26379
第26行:daemonize yes
第31行:pidfile /var/run/redis-sentinel.pid
第65行:dir /usr/local/redis-5.0.14/sentinel
第84行(监控master IP和端口,数字2代表有几个哨兵确认即确认主下线):sentinel monitor mymaster 192.168.111.202 6380 2
第86行(master的redis密码):sentinel auth-pass mymaster 123456
在redis-5.0.14/sentinel/目录下启动:../src/redis-sentinel sentinel.conf
src/redis-cli -p 26379
127.0.0.1:26379> info sentinel
sentinel_masters:1
master0:name=mymaster,status=ok,address=192.168.111.202:6380,slaves=2,sentinels=3
可以看到此时master为192.168.111.202:6380
当我们关闭192.168.111.202的redis时,30秒后
127.0.0.1:26379> info sentinel
sentinel_masters:1
master0:name=mymaster,status=ok,address=192.168.111.204:6380,slaves=2,sentinels=3
当192.168.111.202的master挂掉后,重新选举192.168.111.204为master。
1.当重新选举后会发现 6380/6380.conf 的参数也被修改了:
replicaof 192.168.111.204 6380
2.当重新选举后会发现 sentinel/sentinel.conf 的参数也被修改了:
sentinel monitor mymaster 192.168.111.204 6380 2
java连接哨兵模式测试代码:
package com.util;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
public class SentinelRedisJedisTest {
public static void main(String[] args) {
//1.设置sentinel 各个节点集合
Set<String> sentinelSet = new HashSet<>();
sentinelSet.add("192.168.111.202:26379");
sentinelSet.add("192.168.111.203:26379");
sentinelSet.add("192.168.111.204:26379");
//2.设置jedispool 连接池配置文件
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(10);
config.setMaxWaitMillis(1000);
//3.设置mastername,sentinelNode集合,配置文件,Redis登录密码
JedisSentinelPool jedisSentinelPool
= new JedisSentinelPool("mymaster", sentinelSet, config, "123456");
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
//获取Redis中key=mm的值
String value = jedis.get("mm");
System.out.println(value);
//存储
jedis.set("mm", "123");
jedis.expire("mm", 60);//设置过期时间,秒
System.out.println(jedis.get("mm"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
sentinel.conf 详细参数如下:
port 26379 # 哨兵sentinel实例运行的端口 默认26379
daemonize yes #yes:后台运行;no:不是后台运行
pidfile /var/run/redis-sentinel.pid #记录sentinel的进程号,守护sentinel的安全
logfile "" #指定了记录日志的文件。空字符串的话不保留日志
dir /tmp #数据目录,日志文件也会写在这个目录
sentinel monitor mymaster 127.0.0.1 6379 2 #监控master IP和端口,数字2代表有几个哨兵确认即确认主下线
sentinel auth-pass mymaster 123456 #master的redis密码
sentinel down-after-milliseconds mymaster 30000 #指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
sentinel parallel-syncs mymaster 1 #发生failover主备切换时最多可以有多少个slave同时对新的master进行同步,1表示每次只有一个slave 处于不能处理命令请求的状态
sentinel failover-timeout mymaster 180000 #故障转移的超时时间,默认三分钟
sentinel deny-scripts-reconfig yes # 不允许使用SENTINEL SET设置notification-script和client-reconfig-script。
9.Redis-cluster集群
1.哨兵模式的缺陷
在哨兵模式中,仍然只有一个Master节点。当并发写请求较大时,哨兵模式并不能缓解写压力。
我们知道只有主节点才具有写能力,那如果在一个集群中,能够配置多个主节点,是不是就可以缓解写压力了呢?
答:是的。这个就是redis-cluster集群模式。
2.Redis-cluster集群概念
(1)由多个Redis服务器组成的分布式网络服务集群;
(2)集群之中有多个Master主节点,每一个主节点都可读可写;
(3)节点之间会互相通信,两两相连;
(4)Redis集群无中心节点。
3.集群节点复制
在Redis-Cluster集群中,可以给每一个主节点添加从节点,主节点和从节点直接遵循主从模型的特性。
当用户需要处理更多读请求的时候,添加从节点可以扩展系统的读性能。
4.故障转移
Redis集群的主节点内置了类似Redis Sentinel的节点故障检测和自动故障转移功能,当集群中的某个主节点下线时,集群中的其他在线主节点会注意到这一点,并对已下线的主节点进行故障转移。
集群进行故障转移的方法和Redis Sentinel进行故障转移的方法基本一样,不同的是,在集群里面,故障转移是由集群中其他在线的主节点负责进行的,所以集群不必另外使用Redis Sentinel。
5.集群分片策略
Redis-cluster分片策略,是用来解决key存储位置的
集群将整个数据库分为16384个槽位slot,所有key-value数据都存储在这些slot中的某一个上。一个slot槽位可以存放多个数据,key的槽位计算公式为:slot_number=crc16(key)%16384,其中crc16为16位的循环冗余校验和函数。
集群中的每个主节点都可以处理0个至16383个槽,当16384个槽都有某个节点在负责处理时,集群进入上线状态,并开始处理客户端发送的数据命令请求。
6.集群redirect转向
由于Redis集群无中心节点,请求会随机发给任意主节点;
主节点只会处理自己负责槽位的命令请求,其它槽位的命令请求,该主节点会返回客户端一个转向错误;
客户端根据错误中包含的地址和端口重新向正确的负责的主节点发起命令请求。
192.168.111.203:7002> get mm
-> Redirected to slot [125] located at 192.168.111.202:7001
"123"
192.168.111.202:7001>
192.168.111.202:7001>
比如上面,我明明在 192.168.111.203:7002 节点上 获取 get mm 值,他自动给我切到192.168.111.202:7001 节点上去取的值。
10.集群搭建配置
系统优化参数
# 系统优化没做到位,redis启动后有一些warning报警,可以处理
TCP监听队列大小
即TCP listen的backlog大小,“/proc/sys/net/core/somaxconn”的默认值一般较小如128,需要修改大一点,比如改成32767。立即生效还可以使用命令:sysctl -w net.core.somaxconn=32767。
要想永久生效,需要在文件/etc/sysctl.conf中增加一行:net.core.somaxconn = 32767,然后执行命令“sysctl -p”以生效。
Redis配置项tcp-backlog的值不能超过somaxconn的大小。
OOM相关:vm.overcommit_memory
“/proc/sys/vm/overcommit_memory”默认值为0,表示不允许申请超过CommitLimmit大小的内存。可以设置为1关闭Overcommit,设置方法请参照net.core.somaxconn完成。
/sys/kernel/mm/transparent_hugepage/enabled
默认值为“[always] madvise never”,建议设置为never,以开启内核的“Transparent Huge Pages (THP)”特性,设置后redis进程需要重启。为了永久生效,请将“echo never > /sys/kernel/mm/transparent_hugepage/enabled”加入到文件/etc/rc.local中。
什么是Transparent Huge Pages?为提升性能,通过大内存页来替代传统的4K页,使用得管理虚拟地址数变少,加快从虚拟地址到物理地址的映射,以及摒弃内存页面的换入换出以提高内存的整体性能。内核Kernel将程序缓存内存中,每页内存以2M为单位。相应的系统进程为khugepaged。
在Linux中,有两种方式使用Huge Pages,一种是2.6内核引入的HugeTLBFS,另一种是2.6.36内核引入的THP。HugeTLBFS主要用于数据库,THP广泛应用于应用程序。
一般可以在rc.local或/etc/default/grub中对Huge Pages进行设置。
10.1 集群搭建配置
# 环境
centos 7: 192.168.111.202 redis端口:7001 7002
centos 7: 192.168.111.203 redis端口:7001 7002
centos 7: 192.168.111.204 redis端口:7001 7002
首先需要理清一个概念,就是redis集群总线:
redis集群总线端口为redis客户端端口加上10000,比如我这里redis 使用7001端口为一个节点,那么17001端口为该节点的集群总线端口,注意:每个节点都有一个总线端口。
redis集群至少需要3个主节点,每个主节点有一个从节点总共6个节点。
#开启防火墙
firewall-cmd --zone=public --add-port=7001/tcp --permanent
firewall-cmd --zone=public --add-port=7002/tcp --permanent
firewall-cmd --zone=public --add-port=17001/tcp --permanent
firewall-cmd --zone=public --add-port=17002/tcp --permanent
#重新加载防火墙:
firewall-cmd --reload
# 在对应服务器新建目录
cd /usr/local/redis-5.0.14/
mkdir 7001 7002 # 另外2台服务器对应新建
# 拷贝也拷贝到对应目录下
cp -p redis.conf 7001
cp -p redis.conf 7002
注意所有从节点需要配置一个连接主节点的密码,虽然主节点不需要配置,但当想让主节点切换为从节点时没有配置masterauth 会报错。
vi 7001/redis.conf
# 配置
第69行:bind 192.168.111.202
第92行:port 7001
第136行:daemonize yes
第158行:pidfile /var/run/redis_7001.pid
第171行:logfile "redis.log"
第263行:dir "/usr/local/redis-5.0.14/7001/"
第293行(填写master的密码):masterauth 123456
第507行(设置节点的密码):requirepass 123456
第832行(以集群方式运行):cluster-enabled yes
第840行(集群节点配置文件):cluster-config-file nodes-7001.conf
scp 7001/redis.conf root@192.168.111.203:/usr/local/redis-5.0.14/7001/
scp 7001/redis.conf root@192.168.111.204:/usr/local/redis-5.0.14/7001/
将配置复制到另外2台主机上,记得修改第69行bind ip改成对应服务器的ip
vi 7002/redis.conf
# 配置
第69行:bind 192.168.111.202
第92行:port 7002
第136行:daemonize yes
第158行:pidfile /var/run/redis_7002.pid
第171行:logfile "redis.log"
第263行:dir "/usr/local/redis-5.0.14/7002/"
第293行(填写master的密码):masterauth 123456
第507行(设置节点的密码):requirepass 123456
第832行(以集群方式运行):cluster-enabled yes
第840行(集群节点配置文件):cluster-config-file nodes-7002.conf
scp 7002/redis.conf root@192.168.111.203:/usr/local/redis-5.0.14/7002/
scp 7002/redis.conf root@192.168.111.204:/usr/local/redis-5.0.14/7002/
将配置复制到另外2台主机上,记得修改第69行bind ip改成对应服务器的ip
# 启动redis脚本
start_cluster.sh
#!/bin/bash
cd /usr/local/redis-5.0.14/7001/ && /usr/local/redis-5.0.14/src/redis-server redis.conf
cd /usr/local/redis-5.0.14/7002/ && /usr/local/redis-5.0.14/src/redis-server redis.conf
# 启动redis
chmod +x start_cluster.sh
./start_cluster.sh
# 重启
重启实例之前你要删除以下文件:
rm -rf nodes-7001.conf nodes-7002.conf
rm -rf dump.rdb
rm -rf appendonly.aof
10.2 执行创建集群命令
执行命令后需要根据提示输入:yes
src/redis-cli -a '123456' --cluster create 192.168.111.202:7001 192.168.111.203:7001 192.168.111.204:7001 192.168.111.202:7002 192.168.111.203:7002 192.168.111.204:7002 --cluster-replicas 1
# -a 123456 表示密码为123456
# --cluster-replicas 1 表示主从配置比,1表示的是1:1,前三个是主,后三个是从。
我这里192.168.111.202:7001 192.168.111.203:7001 192.168.111.204:7001 三个是主,注意3个主节点都有自己的总线端口17001
192.168.111.202:7002 192.168.111.203:7002 192.168.111.204:7002 三个是从,注意3个主节点都有自己的总线端口17002。
10.3 查询集群信息
节点客户端连接命令:
src/redis-cli -c -h 192.168.111.202 -p 7001 -a '123456'
参数说明:
-c:表示以集群方式连接redis,不加表示进入单机redis
-h:指定IP地址
-p:指定端口
cluster nodes:查询集群节点信息
cluster info:查询集群状态信息
[root@centos00 redis-5.0.14]# src/redis-cli -c -h 192.168.111.202 -p 7001 -a '123456'
192.168.111.202:7001> cluster nodes
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1648259155000 6 connected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648259157000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648259159593 3 connected 10923-16383
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648259158469 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648259156223 4 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648259160732 5 connected
java连接cluster集群测试代码:
package com.util;
import redis.clients.jedis.*;
import java.util.HashSet;
import java.util.Set;
/**
* Cluster集群模式连接测试
* @Date: 2022/3/20 19:59
*/
public class ClusterRedisJedisTest {
public static void main(String[] args) {
//1.设置cluster 各个节点集合
Set<HostAndPort> nodes = new HashSet<HostAndPort>();
nodes.add(new HostAndPort("192.168.111.202", 7001));
nodes.add(new HostAndPort("192.168.111.202", 7002));
nodes.add(new HostAndPort("192.168.111.203", 7001));
nodes.add(new HostAndPort("192.168.111.203", 7002));
nodes.add(new HostAndPort("192.168.111.204", 7001));
nodes.add(new HostAndPort("192.168.111.204", 7002));
//2.设置jedispool 连接池配置文件
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(60000);//设置最大连接数
config.setMaxIdle(1000); //设置最大空闲数
config.setMaxWaitMillis(3000);//设置超时时间
//在borrow(引入)一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
config.setTestOnBorrow(true);
//return 一个jedis实例给pool时,是否检查连接可用性(ping())
config.setTestOnReturn(true);
//3.设置,配置文件,Redis登录密码
// JedisCluster jedis = new JedisCluster(nodes, config);
//int connectionTimeout,
int connectionTimeout = 6000;//默认2000
int socketTimeout = 6000;//默认2000
int maxAttempts = 5;//在JedisCluster模式下,您可以配置maxAttempts参数来定义失败时的重试次数(默认值为5)。
String password = "123456";
JedisCluster jedis = new JedisCluster(nodes, connectionTimeout, socketTimeout, maxAttempts, password, config);
try {
//获取Redis中key=mm的值
String value = jedis.get("mm");
System.out.println(value);
//存储
jedis.set("mm", "123");
jedis.expire("mm", 60);//设置过期时间,秒
System.out.println(jedis.get("mm"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
10.4 测试故障性转移
# 模拟故障192.168.111.204:7002节点命令:debug segfault
[root@centos00 redis-5.0.14]# src/redis-cli -a 123456 -h 192.168.111.204 -p 7002 debug segfault
Error: Server closed the connection
## 发现192.168.111.204:7002@17002 slave,fail已经发生故障
[root@centos00 redis-5.0.14]# src/redis-cli -c -h 192.168.111.202 -p 7001 -a '123456'
192.168.111.202:7001> cluster nodes
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave,fail 367741512e61a297e5629eec3ba3f0d32a11a89f 1648259587289 1648259585583 6 disconnected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648259629000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648259636829 3 connected 10923-16383
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648259633412 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648259634551 4 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648259635690 5 connected
重新启动故障redis
/usr/local/redis-5.0.14/src/redis-server /usr/local/redis-5.0.14/7002/redis.conf
#故障节点已经恢复
192.168.111.202:7001> cluster nodes
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1648259805752 6 connected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648259806000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648259809965 3 connected 10923-16383
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648259808826 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648259811103 4 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648259809000 5 connected
10.5 集群管理
新增克隆一台服务器,192.168.111.205 redis端口:7001 7002,按照上面的方式配置,并启动。
# 1.添加新的主节点
redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-master-id node_id
new_host:new_port 为要新添加的主节点IP和端口,此处是192.168.111.205:7001
existing_host:existing_port 表示的是已存在的一个主节点的IP和端口,这个可以从上述的节点信息中查看到,比如192.168.111.204:7001这个节点,对应的节点槽数是10923-16383,16383表示的是最后的槽数。
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648259809965 3 connected 10923-16383
--cluster-master-id 表示的是新添加的主节点要在这个节点后面
比如这里一个旧的主节点:
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648259809965 3 connected 10923-16383
准备好的新节点192.168.111.205:7001(先手动启动):/usr/local/redis-5.0.14/src/redis-server /usr/local/redis-5.0.14/7001/redis.conf
[root@centos00 redis-5.0.14]# src/redis-cli -a '123456' --cluster add-node 192.168.111.205:7001 192.168.111.204:7001 --cluster-master-id 1778e9f87119ce4c87680e157037dbeab8931522
>>> Adding node 192.168.111.205:7001 to cluster 192.168.111.204:7001
>>> Performing Cluster Check (using node 192.168.111.204:7001)
##新节点已经加进来了
192.168.111.202:7001> cluster nodes
4ad88045d0d2454fcd92e74c4c047854e39d0273 192.168.111.205:7001@17001 master - 0 1648260628030 0 connected
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1648260631000 6 connected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648260630000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648260630307 3 connected 10923-16383
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648260629167 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648260633725 4 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648260632587 5 connected
# 2.hash槽重新分配
# 添加完新节点后,需要对新添加的主节点进行hash槽重新分配,这样该主节点才能存储数据,redis共有16384个槽。(node_id必须都是主节点)
redis-cli --cluster reshard host:port --cluster-from node_id --cluster-to node_id --cluster-slots <args> --cluster-yes
# 例子说明
host:port表示的是新添加的那个主节点IP和端口,此处表示的是192.168.111.205:7001
--cluster-from node_id 表示的是要从哪一个主节点,分一些槽。
--cluster-to node_id 表示新添加的那个主节点id
--cluster-slots 500 表示的是给新主节点分配多少个槽位,范围:--cluster-from 节点的开始 --> 开始位置+500
--cluster-yes 表示的是自动应答为yes,若不加上这个会让手动输入yes,表示同意此次分配
4ad88045d0d2454fcd92e74c4c047854e39d0273 192.168.111.205:7001@17001 master - 0 1648260628030 0 connected
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648260630307 3 connected 10923-16383
src/redis-cli -a '123456' --cluster reshard 192.168.111.205:7001 --cluster-from 1778e9f87119ce4c87680e157037dbeab8931522 --cluster-to 4ad88045d0d2454fcd92e74c4c047854e39d0273 --cluster-slots 500 --cluster-yes
重新分配后的节点
192.168.111.204:7001 槽位由 10923-16383 变成 11423-16383
192.168.111.205:7001 新增节点分得的槽位 10923-11422
192.168.111.202:7001> cluster nodes
4ad88045d0d2454fcd92e74c4c047854e39d0273 192.168.111.205:7001@17001 master - 0 1648261272916 7 connected 10923-11422
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1648261270000 6 connected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648261264000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648261271000 3 connected 11423-16383
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648261270633 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648261271774 4 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648261269495 5 connected
# 3.添加新从节点
准备好的新节点192.168.111.205:7002(先手动启动):/usr/local/redis-5.0.14/src/redis-server /usr/local/redis-5.0.14/7002/redis.conf
redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id node_id
new_host:new_port 表示的是新添加从节点的IP和端口,此处表示的是192.168.111.205:7002
existing_host:existing_port 表示主节点的ip和端口。 192.168.111.205:7001。
---cluster-master-id node_id 表示主节点的id。要个哪个主节点添加从节点。
例如:
[root@centos00 redis-5.0.14]# src/redis-cli -a '123456' --cluster add-node 192.168.111.205:7002 192.168.111.205:7001 --cluster-slave --cluster-master-id 4ad88045d0d2454fcd92e74c4c047854e39d0273
>>> Adding node 192.168.111.205:7002 to cluster 192.168.111.205:7001
>>> Performing Cluster Check (using node 192.168.111.205:7001)
192.168.111.202:7001> cluster nodes
4ad88045d0d2454fcd92e74c4c047854e39d0273 192.168.111.205:7001@17001 master - 0 1648262108144 7 connected 10923-11422
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1648262102000 6 connected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648262088000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648262105867 3 connected 11423-16383
3901bb99277329c25c6e69cc65d78c284e3731ad 192.168.111.205:7002@17002 slave 4ad88045d0d2454fcd92e74c4c047854e39d0273 0 1648262104727 7 connected
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648262107005 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648262102449 4 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648262103588 5 connected
# 4.删除节点
redis-cli --cluster del-node host:port node_id
例如:
3901bb99277329c25c6e69cc65d78c284e3731ad 192.168.111.205:7002@17002 slave 4ad88045d0d2454fcd92e74c4c047854e39d0273 0 1648262104727 7 connected
##从节点直接就可以删除
[root@centos00 redis-5.0.14]# src/redis-cli -a '123456' --cluster del-node 192.168.111.205:7002 3901bb99277329c25c6e69cc65d78c284e3731ad
>>> Removing node 3901bb99277329c25c6e69cc65d78c284e3731ad from cluster 192.168.111.205:7002
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
删除后可以发现刚添加的从节点已经消失了
192.168.111.202:7001> cluster nodes
4ad88045d0d2454fcd92e74c4c047854e39d0273 192.168.111.205:7001@17001 master - 0 1648262369048 7 connected 10923-11422
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1648262373574 6 connected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648262365000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648262370171 3 connected 11423-16383
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648262373574 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648262371311 4 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648262372434 5 connected
## 如果删除的节点是主节点,首先要把节点中的哈希槽转移到其他节点中
4ad88045d0d2454fcd92e74c4c047854e39d0273 192.168.111.205:7001@17001 master - 0 1648262369048 7 connected 10923-11422
删除192.168.111.205:7001 主节点,删除前先将节点的槽中的数据转移到其他主节点中
src/redis-cli -a '123456' --cluster reshard 192.168.111.205:7001
M: 4ad88045d0d2454fcd92e74c4c047854e39d0273 192.168.111.205:7001
slots:[10923-11422] (500 slots) master
How many slots do you want to move (from 1 to 16384)?
您想移动多少个插槽(从1到16384)?这里输入 500,因为这个主节点有500个槽位,上面提示很清楚了。
What is the receiving node ID?
接收节点ID是什么?输入192.168.111.204:7001 节点ID
Source node #1:
这个提示 输入要删除主节点的ID, 4ad88045d0d2454fcd92e74c4c047854e39d0273
Source node #2:
这个提示 输入:done
Do you want to proceed with the proposed reshard plan (yes/no)?
这个迁移计划提示 输入:yes
可以发现192.168.111.205:7001节点,已经没有槽位了,192.168.111.204:7001节点槽位多了500个。
## 可以发现192.168.111.205:7001节点,已经没有槽位了
192.168.111.202:7001> cluster nodes
4ad88045d0d2454fcd92e74c4c047854e39d0273 192.168.111.205:7001@17001 master - 0 1648262884000 7 connected
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1648262887537 6 connected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648262879000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648262889458 8 connected 10923-16383
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648262890602 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648262887195 8 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648262888333 5 connected
移完成 然后再使用用del-node命令删除192.168.111.205:7001 主节点即
[root@centos00 redis-5.0.14]# src/redis-cli -a '123456' --cluster del-node 192.168.111.205:7001 4ad88045d0d2454fcd92e74c4c047854e39d0273
>>> Removing node 4ad88045d0d2454fcd92e74c4c047854e39d0273 from cluster 192.168.111.205:7001
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
192.168.111.205:7001节点已经消失了。
192.168.111.202:7001> cluster nodes
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1648263010204 6 connected
e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 192.168.111.202:7001@17001 myself,master - 0 1648263005000 1 connected 0-5460
1778e9f87119ce4c87680e157037dbeab8931522 192.168.111.204:7001@17001 master - 0 1648263012000 8 connected 10923-16383
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1648263012453 2 connected 5461-10922
e07b0d9beea5126771c5dcd3bae93f623754245d 192.168.111.202:7002@17002 slave 1778e9f87119ce4c87680e157037dbeab8931522 0 1648263014719 8 connected
b74a1f76c235d1e22a9626f44198189c17a3f4d8 192.168.111.203:7002@17002 slave e7e9a953a2dda80243cff90c5fc9de8bd9b9e190 0 1648263013593 5 connected
11.人工手动切换主从
在需要变为主节点的slave上执行
192.168.111.204:7002> cluster nodes
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 myself,slave 367741512e61a297e5629eec3ba3f0d32a11a89f 0 1650658071000 6 connected
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 master - 0 1650658071000 2 connected 5461-10922
192.168.111.204:7002> cluster failover OK # 然后查看就可以发现从slave 变为myself,master
192.168.111.204:7002> cluster nodes
1a41a05007b811afb34b7debc57639acc31d15dd 192.168.111.204:7002@17002 myself,master - 0 1650658147000 9 connected 5461-10922
367741512e61a297e5629eec3ba3f0d32a11a89f 192.168.111.203:7001@17001 slave 1a41a05007b811afb34b7debc57639acc31d15dd 0 1650658148542 9 connected
12.大压力下redis参数调整要点
为何大压力下要这样调整?
最重要的原因之一Redis的主从复制,两者复制共享同一线程,虽然是异步复制的,但因为是单线程,所以也十分有限。如果主从间的网络延迟不是在0.05左右,比如达到0.6,甚至1.2等,那么情况是非常糟糕的,因此同一Redis集群一定要部署在同一机房内。
这些参数的具体值,要视具体的压力而定,而且和消息的大小相关,比如一条200~500KB的流水数据可能比较大,主从复制的压力也会相应增大,而10字节左右的消息,则压力要小一些。大压力环境中开启appendfsync是十分不可取的,容易导致整个集群不可用,在不可用之前的典型表现是QPS毛刺明显。
这么做的目的是让Redis集群尽可能的避免master正常时触发主从切换,特别是容纳的数据量很大时,和大压力结合在一起,集群会雪崩
参数 | 建议最小值 | 说明 |
repl-ping-slave-period | 10 | 每10秒ping一次 |
repl-timeout | 60 | 60秒超时,也就是ping十次 |
cluster-node-timeout | 15000 | |
repl-backlog-size | 1GB | Master对slave的队列大小 |
appendfsync | no | 让系统自动刷 |
save | 大压力下,调大参数值,以减少写RDB带来的压力: "900 20 300 200 60 200000" | |
appendonly | 对于队列,建议单独建立集群,并且设置该值为no |
参考: