redis

redis

redis定义

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。 [1]

Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

部署和使用

redis部署

编译安装

1.安装依赖包
[root@localhost ~]# yum install gcc jemalloc-devel -y

#若要支持systemd就添加systemd-devel

[root@localhost ~]# yum -y install gcc jemalloc-devel systemd-devel

2.下载redis安装包
[root@localhost ~]# mkdir /data
[root@localhost ~]# cd /data
[root@localhost data]# wget http://download.redis.io/releases/redis-5.0.7.tar.gz
--2024-07-12 15:57:29--  http://download.redis.io/releases/redis-5.0.7.tar.gz
正在解析主机 download.redis.io (download.redis.io)... 45.60.125.1
正在连接 download.redis.io (download.redis.io)|45.60.125.1|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:1984203 (1.9M) [application/octet-stream]
正在保存至: “redis-5.0.7.tar.gz”

100%[=======================================>] 1,984,203   2.10MB/s 用时 0.9s   

2024-07-12 15:57:30 (2.10 MB/s) - 已保存 “redis-5.0.7.tar.gz” [1984203/1984203])


3.解压
[root@localhost data]# tar xf redis-5.0.7.tar.gz 
[root@localhost data]# ls
redis-5.0.7  redis-5.0.7.tar.gz

4.编译安装
[root@localhost data]# cd redis-5.0.7/
[root@centos7 redis-5.0.7]# make PREFIX=/apps/redis install 
#指定redis安装目录

[root@centos7 redis-5.0.7]# make USE_SYSTEMD=yes PREFIX=/apps/redis install
#如果支持systemd,需要执行下面

5.配置变量
[root@localhost ~]# echo 'PATH=/apps/redis/bin:$PATH' > /etc/profile.d/redis.sh
[root@localhost ~]#. /etc/profile.d/redis.sh

6.准备配置文件及目录
[[root@localhost ~]# mkdir /apps/redis/{etc,log,data,run}
#创建配置文件、日志、数据等目录

[root@localhost redis-5.0.7]#cp redis.conf /apps/redis/etc/
#源码包中自带 配置文件

7.启动redis
[root@localhost ~]# redis-cli 
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected> 

[root@localhost ~]# redis-server /apps/redis/etc/redis.conf
#指定配置文件启动(前台启动)


systemd 启动
[root@localhost ~]#useradd -r -s /sbin/nologin redis			
#创建执行redis的执行用户
[root@localhost ~]#chown -R redis.redis /apps/redis/		
#为文件夹添加执行权限
[root@localhost ~]#ln -s /apps/redis/bin/redis-* /usr/bin/		
#为文件设置软链接

#准备service文件
[root@localhost ~]#vim /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支持systemd可以启用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target



#启动redis
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl start  redis


yum安装

[root@localhost ~]# yum install epel-release.noarch -y
#安装epel源,查看redis的安装包
[root@localhost ~]# yum info redis
可安装的软件包
名称    :redis
架构    :x86_64
版本    :3.2.12
发布    :2.el7
大小    :544 k
源    :epel/x86_64
简介    : A persistent key-value database
网址    :http://redis.io
协议    : BSD
[root@localhost ~]# yum install redis -y 		#yum安装redis

redis多实例

测试环境中经常使用多实例,需要指定不同实例的相应的端口,配置文件,日志文件等相关配置

范例: 以编译安装为例实现 redis 多实例

可以共同使用一个配置文件,建议分开各个文件

#  做之前先关闭初始的  redis 数据库

[root@localhost ~]# cd /apps/redis/etc/
[root@node2 etc]#cp  /apps/redis/etc/redis.conf   /apps/redis/etc/redis6379.conf 
[root@node2 etc]#cp  /apps/redis/etc/redis.conf   /apps/redis/etc/redis6380.conf
[root@node2 etc]#cp  /apps/redis/etc/redis.conf   /apps/redis/etc/redis6381.conf
#准备配置文件

[root@node2 etc]#grep dump.rdb redis6379.conf 
#修改 备份文件的名字
dbfilename dump.rdb
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6379.rdb/'  redis6379.conf 
[root@node2 etc]#grep dump   redis6379.conf 
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6380.rdb/'  redis6380.conf 
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6381.rdb/'  redis6381.conf


#修改日志文件
[root@node2 etc]#grep   "logfile"  redis6379.conf 
logfile ""

[root@node2 etc]#sed  -i  's#logfile ""#logfile /apps/redis/log/redis6379.log#'  redis6379.conf 
[root@node2 etc]#grep   "logfile"  redis6379.conf 
logfile /apps/redis/log/redis6379.log

[root@node2 etc]#sed  -i  's#logfile ""#logfile /apps/redis/log/redis6380.log#'  redis6380.conf 
[root@node2 etc]#grep   "logfile"  redis6380.conf 
logfile /apps/redis/log/redis6380.log

[root@node2 etc]#sed  -i  's#logfile ""#logfile /apps/redis/log/redis6381.log#'  redis6381.conf 
[root@node2 etc]#grep   "logfile"  redis6381.conf 
logfile /apps/redis/log/redis6381.log

#修改pid文件
[root@node2 etc]#grep   "pidfile"  redis6379.conf 
#6379 不用改了
pidfile /var/run/redis_6379.pid

[root@node2 etc]#sed -i   's/redis_6379.pid/redis_6380.pid/'   redis6380.conf 
[root@node2 etc]#sed -i   's/redis_6379.pid/redis_6381.pid/'   redis6381.conf 

[root@node2 etc]#grep   "pidfile"  redis6380.conf 
pidfile /var/run/redis_6380.pid
[root@node2 etc]#grep   "pidfile"  redis6381.conf 
pidfile /var/run/redis_6381.pid


#修改端口号
[root@node2 etc]#sed  -i  's/^port 6379/port 6380/'  redis6380.conf
[root@node2 etc]#sed  -i  's/^port 6379/port 6381/'  redis6381.conf



#准备service文件
[root@node2 apps]#cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6379.service
[root@node2 apps]#cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6380.service
[root@node2 apps]#cp  /lib/systemd/system/redis.service     /lib/systemd/system/redis6381.service
[Unit]
Description=Redis persistent key-value database
After=network.target


[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6379.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支持systemd可以启用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755


[Install]
WantedBy=multi-user.target

[Unit]
Description=Redis persistent key-value database
After=network.target


[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6380.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支持systemd可以启用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755


[Install]
WantedBy=multi-user.target


[Unit]
Description=Redis persistent key-value database
After=network.target


[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6381.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支持systemd可以启用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target


[root@node2 apps]#chown redis.redis /apps/redis/   -R


#测试   info  指令
[root@node2 apps]#redis-cli 
[root@node2 apps]#redis-cli -p  6380
[root@node2 apps]#redis-cli -p  6381

redis 的配置

bind 0.0.0.0 		
#监听地址,可以用空格隔开后多个监听IP

protected-mode yes 	
#redis3.2之后加入的新特性,在没有设置bind IP和密码的时候,redis只允许访问127.0.0.1:6379,可以远程连接,但当访问将提示警告信息并拒绝远程访问

port 6379 			
#监听端口,默认6379/tcp

tcp-backlog 511 ·	
#三次握手的时候server端收到client ack确认号之后的队列值,即全连接队列长度timeout 0			
#客户端和Redis服务端的连接超时时间,默认是0,表示永不超时

tcp-keepalive 300 	
#tcp 会话保持时间300s

daemonize no 		
#默认no,即直接运行redis-server程序时,不作为守护进程运行,而是以前台方式运行,如果想在后台运行需改成yes,当redis作为守护进程运行的时候,它会写一个 pid 到/var/run/redis.pid 文件

supervised no 		
#和OS相关参数,可设置通过upstart和systemd管理Redis守护进程,centos7后都使用systemd

pidfile /var/run/redis_6379.pid 
#pid文件路径,可以修改为/apps/redis/run/redis_6379.pid

loglevel notice		
#日志级别

logfile "/path/redis.log" 
#日志路径,示例:logfile "/apps/redis/log/redis_6379.log"databases 16 #设置数据库数量,默认:0-15,共16个库

always-show-logo yes 
#在启动redis 时是否显示或在日志中记录记录redis的logo

save 900 1 
#在900秒内有1个key内容发生更改,就执行快照机制
save 300 10 
#在300秒内有10个key内容发生更改,就执行快照机制
save 60  10000  
#60秒内如果有10000个key以上的变化,就自动快照备份

stop-writes-on-bgsave-error yes 
#默认为yes时,可能会因空间满等原因快照无法保存出错时,会禁止redis写入操作,生产建议为no 
#此项只针对配置文件中的自动save有效

rdbcompression yes 
#持久化到RDB文件时,是否压缩,"yes"为压缩,"no"则反之

rdbchecksum yes
#是否对备份文件开启RC64校验,默认是开启

dbfilename dump.rdb 
#快照文件名

dir ./ 
#快照文件保存路径,示例:dir "/apps/redis/data"
#主从复制相关
# replicaof <masterip> <masterport> #指定复制的master主机地址和端口,5.0版之前的指令为slaveof 
# masterauth <master-password> #指定复制的master主机的密码

replica-serve-stale-data yes #当从库同主库失去连接或者复制正在进行,从机库有两种运行方式:
1、设置为yes(默认设置),从库会继续响应客户端的读请求,此为建议值
2、设置为no,除去特定命令外的任何请求都会返回一个错误"SYNC with master in progress"。


replica-read-only yes 
#是否设置从库只读,建议值为yes,否则主库同步从库时可能会覆盖数据,造成数据丢失

repl-diskless-sync no 
#是否使用socket方式复制数据(无盘同步),新slave第一次连接master时需要做数据的全量同步,redis server就要从内存dump出新的RDB文件,然后从master传到slave,有两种方式把RDB文件传输给客户端:
1、基于硬盘(disk-backed):为no时,master创建一个新进程dump生成RDB磁盘文件,RDB完成之后由父进程(即主进程)将RDB文件发送给slaves,此为默认值
2、基于socket(diskless):master创建一个新进程直接dump RDB至slave的网络socket,不经过主进程和硬盘
#推荐使用基于硬盘(为no),是因为RDB文件创建后,可以同时传输给更多的slave,但是基于socket(为yes), 新slave连接到master之后得逐个同步数据。只有当磁盘I/O较慢且网络较快时,可用diskless(yes),否则一般建议使用磁盘(no)

repl-diskless-sync-delay 5 
#diskless时复制的服务器等待的延迟时间,设置0为关闭,在延迟时间内到达的客户端,会一起通过diskless方式同步数据,但是一旦复制开始,master节点不会再接收新slave的复制请求,直到下一次同步开始才再接收新请求。即无法为延迟时间后到达的新副本提供服务,新副本将排队等待下一次RDB传输,因此服务器会等待一段时间才能让更多副本到达。推荐值:30-60

repl-ping-replica-period 10 
#slave根据master指定的时间进行周期性的PING master,用于监测master状态,默认10s

repl-timeout 60 
#复制连接的超时时间,需要大于repl-ping-slave-period,否则会经常报超时

repl-disable-tcp-nodelay no 
#是否在slave套接字发送SYNC之后禁用 TCP_NODELAY,如果选择"yes",Redis将合并多个报文为一个大的报文,从而使用更少数量的包向slaves发送数据,但是将使数据传输到slave上有延迟,Linux内核的默认配置会达到40毫秒,如果 "no" ,数据传输到slave的延迟将会减少,但要使用更多的带宽

repl-backlog-size 512mb 
#复制缓冲区内存大小,当slave断开连接一段时间后,该缓冲区会累积复制副本数据,因此当slave 重新连接时,通常不需要完全重新同步,只需传递在副本中的断开连接后没有同步的部分数据即可。只有在至少有一个slave连接之后才分配此内存空间,建议建立主从时此值要调大一些或在低峰期配置,否则会导致同步到slave失败

repl-backlog-ttl 3600 
#多长时间内master没有slave连接,就清空backlog缓冲区

replica-priority 100 
#当master不可用,哨兵Sentinel会根据slave的优先级选举一个master,此值最低的slave会优先当选master,而配置成0,永远不会被选举,一般多个slave都设为一样的值,让其自动选择
#min-replicas-to-write 3 #至少有3个可连接的slave,mater才接受写操作
#min-replicas-max-lag 10 #和上面至少3个slave的ping延迟不能超过10秒,否则master也将停止写操作

requirepass foobared 
#设置redis连接密码,之后需要AUTH pass,如果有特殊符号,用" "引起来,生产建议设置

rename-command 
#重命名一些高危命令,示例:rename-command FLUSHALL "" 禁用命令
#示例: rename-command FLUSHALL   123456
   
maxclients 10000 
#Redis最大连接客户端
 
maxmemory <bytes> 
#redis使用的最大内存,单位为bytes字节,0为不限制,建议设为物理内存一半,8G内存的计算方式8(G)*1024(MB)1024(KB)*1024(Kbyte),需要注意的是缓冲区是不计算在maxmemory内,生产中如果不设置此项,可能会导致OOM


appendonly no 
#是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能

appendfilename "appendonly.aof" 
#文本文件AOF的文件名,存放在dir指令指定的目录中

appendfsync everysec 
#aof持久化策略的配置
#no表示由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据
#always表示每次写入都执行fsync,以保证数据同步到磁盘,安全性高,性能较差
#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据,此为默认值,也生产建议值

#同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,以下参数实现控制

no-appendfsync-on-rewrite no 
#在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。#默认为no,表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题
#为yes,相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?Linux默认fsync策略是30秒,最多会丢失30s的数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐
#rewrite 即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间


auto-aof-rewrite-percentage 100 
#当Aof log增长超过指定百分比例时,重写AOF文件,设置为0表示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据


auto-aof-rewrite-min-size 64mb
#触发aof rewrite的最小文件大小

aof-load-truncated yes 
#是否加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电等),建议yes

aof-use-rdb-preamble no 
#redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重写产生的文件将同时包含RDB格式的内容和AOF格式的内容,其中RDB格式的内容用于记录已有的数据,而AOF格式的内容则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持久化和AOF持久化的优点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据),默认为no,即不启用此功能

lua-time-limit 5000 
#lua脚本的最大执行时间,单位为毫秒

cluster-enabled yes 
#是否开启集群模式,默认不开启,即单机模式

cluster-config-file nodes-6379.conf
#由node节点自动生成的集群配置文件名称

cluster-node-timeout 15000 
#集群中node节点连接超时时间,单位ms,超过此时间,会踢出集群

cluster-replica-validity-factor 10 
#单位为次,在执行故障转移的时候可能有些节点和master断开一段时间导致数据比较旧,这些节点就不适用于选举为master,超过这个时间的就不会被进行故障转移,不能当选master,计算公式:(node-timeout * replica-validity-factor) + repl-pingreplica-period

cluster-migration-barrier 1 
#集群迁移屏障,一个主节点至少拥有1个正常工作的从节点,即如果主节点的slave节点故障后会将多余的从节点分配到当前主节点成为其新的从节点。

cluster-require-full-coverage yes 
#集群请求槽位全部覆盖,如果一个主库宕机且没有备库就会出现集群槽位不全,那么yes时redis集群槽位验证不全,就不再对外提供服务(对key赋值时,会出现CLUSTERDOWN The cluster is down的提示,cluster_state:fail,但ping 仍PONG),而no则可以继续使用,但是会出现查询数据查不到的情况(因为有数据丢失)

cluster-replica-no-failover no 
#如果为yes,此选项阻止在主服务器发生故障时尝试对其主服务器进行故障转移。 但是,主服务器仍然可以执行手动强制故障转移,一般为no
#Slow log 是 Redis 用来记录超过指定执行时间的日志系统,执行时间不包括与客户端交谈,发送回复等I/O操作,而是实际执行命令所需的时间(在该阶段线程被阻塞并且不能同时为其它请求提供服务),由于slow log 保存在内存里面,读写速度非常快,因此可放心地使用,不必担心因为开启 slow log 而影响Redis 的速度

slowlog-log-slower-than 10000 
#以微秒为单位的慢日志记录,为负数会禁用慢日志,为0会记录每个命令操作。默认值为10ms,一般一条命令执行都在微秒级,生产建议设为1ms-10ms之间

slowlog-max-len 128 
#最多记录多少条慢日志的保存队列长度,达到此长度后,记录新命令会将最旧的命令从命令队列中删除,以此滚动删除,即,先进先出,队列固定长度,默认128,值偏小,生产建议设为1000以上
#设置连接密码
127.0.0.1:6379> CONFIG SET requirepass 123456
OK
#设置最大内存
127.0.0.1:6379> CONFIG SET maxmemory 8589934592
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "8589934592"

Redis 相关命令

INFO

显示当前节点redis运行状态信息

127.0.0.1:6379> INFO
# Server
redis_version:5.0.3
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:8c0bf22bfba82c8f
redis_mode:standalone
os:Linux 4.18.0-147.el8.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:8.2.1
process_id:725
run_id:8af0d3fba2b7c5520e0981b125cc49c3ce4d2a2f tcp_port:6379
uptime_in_seconds:18552

select

切换数据库,相当于在MySQL的 USE DBNAME 指令

[root@centos8 ~]#redis-cli
127.0.0.1:6379> info cluster
# Cluster
cluster_enabled:0
127.0.0.1:6379[15]> SELECT 0
OK
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> SELECT 15
OK
127.0.0.1:6379[15]> SELECT 16
(error) ERR DB index is out of range 127.0.0.1:6379[15]>

注意: 在 redis cluster 模式下不支持多个数据库,会出现下面错误

[root@centos8 ~]#redis-cli 
127.0.0.1:6379> info cluster
# Cluster
cluster_enabled:1
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> select 1
(error) ERR SELECT is not allowed in cluster mode

keys

查看当前库下的所有keys,此命令慎用!

127.0.0.1:6379> KEYS *
1) "9527"
2) "9526"
3) "paihangbang"
4) "list1"

#支持通配符
redis> KEYS *o*
1) "four"
2) "two"
3) "one"

redis> KEYS t??
1) "two"

redis> KEYS *  # 匹配数据库内所有 
key 1) "four"
2) "three"
3) "two"
4) "one"

MSET

一次性设置多个key

redis>MSET one 1 two 2 three 3 four 4  # 一次设置 4 个 key OK

BGSAVE

手动在后台执行RDB持久化操作

127.0.0.1:6379[1]> BGSAVE
Background saving started

DBSIZE

返回当前库下的所有key 数量

127.0.0.1:6379> DBSIZE
(integer) 4
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> DBSIZE (integer) 0

FLUSHDB

强制清空当前库中的所有key,此命令慎用

127.0.0.1:6379> DBSIZE
(integer) 4
127.0.0.1:6379> FLUSHDB
OK
127.0.0.1:6379> DBSIZE
(integer) 0
127.0.0.1:6379>

FLUSHALL

强制清空当前redis服务器所有数据库中的所有key,即删除所有数据,此命令慎用!

127.0.0.1:6379> FLUSHALL OK

#生产建议修改配置 /etc/redis.conf 
rename-command FLUSHALL ""
#rename-command 在6.2.4版淘汰了

SHUTDOWN

# 停止所有客户端


如果有至少一个保存点在等待,执行 SAVE 命令
如果 AOF 选项被打开,更新 AOF 文件
关闭 redis 服务器(server)
如果持久化被打开的话, SHUTDOWN 命令会保证服务器正常关闭而不丢失任何数据。
另一方面,假如只是单纯地执行 SAVE 命令,然后再执行 QUIT 命令,则没有这一保证 —— 因为在执行SAVE 之后、执行 QUIT 之前的这段时间中间,其他客户端可能正在和服务器进行通讯,这时如果执行 QUIT 就会造成数据丢失。

redis数据类型

字符串string

字符串是所有编程语言中最常见的和最常用的数据类型,而且也是redis最基本的数据类型之一,而且redis 中所有的 key 的类型都是字符串。常用于保存 Session 信息场景,此数据类型比较常用

image-20240707235504825

使用例子

set 指令可以创建一个key 并赋值, 使用格式

SETkeyvalue [EX seconds] [PX milliseconds] [NX|XX]时间复杂度: O(1)
将字符串值 value 关联到 key 

如果 key 已经持有其他值, SET 就覆写旧值,无视类型。
当 SET 命令对一个带有生存时间(TTL)的键进行设置之后,该键原有的 TTL 将被清除。

从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改:
EX seconds :将键的过期时间设置为 seconds 秒。执行 SET key value EX seconds 的效果等同于执行 SETEX key seconds value 。

PX milliseconds :将键的过期时间设置为 milliseconds 毫秒。执行 SET key value PX 

milliseconds 的效果等同于执行 PSETEX key milliseconds value 。

NX :只在键不存在时,才对键进行设置操作。执行 SET key value NX 的效果等同于执行 SETNX key value 。

XX :只在键已经存在时,才对键进行设置操作。

例子: 不论key是否存在.都设置

set

127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> get key1
"value1"

例子:判断类型

type

127.0.0.1:6379> TYPE key1  #判断类型
string

例子:设置自动过期

ex

127.0.0.1:6379> SET title ceo ex 3#设置自动过期时间3s OK

例子:key不存在,才设置,相当于add

setnx

127.0.0.1:6379> set title
"ceo"
127.0.0.1:6379> setnx title coo  #set key value nx 
(integer) 0
127.0.0.1:6379> get title
"ceo"

例子: xx 指令key存在,才设置,相当于update

xx

127.0.0.1:6379> get title
"ceo"
127.0.0.1:6379> set title coo xx 
OK
127.0.0.1:6379> get title
"coo"

127.0.0.1:6379> get age
(nil)
127.0.0.1:6379> set age 20 xx
(nil)
127.0.0.1:6379> get age
(nil)

例子: 删除key

del

127.0.0.1:6379> DEL key1 
(integer) 1

例子: 批量设置多个key

mset

127.0.0.1:6379> MSET key1 value1 key2 value2
OK

例子: 获取多个key

mget

127.0.0.1:6379> MGET key1 key2 1) "value1"
2) "value2"

例子: 追加数据

APPEND

127.0.0.1:6379> set key1 123
OK
127.0.0.1:6379> append key1 "cxk"
(integer) 6
127.0.0.1:6379> get key1
"123cxk"

例子: 返回字符串 key 对应值的字节数

STRLEN

127.0.0.1:6379> STRLEN key1
(integer) 6

例子: 判断key 是否存在

EXISTS

127.0.0.1:6379> EXISTS name  
(integer) 0

例子 :查看超时时间

ttl key #查看key的剩余生存时间,如果key过期后,会自动删除

  • -1#返回值表示永不过期,默认创建的key是永不过期,重新对key赋值,也会从有剩余生命周期变成永不过期
  • -2#返回值表示没有此key
  • num #key的剩余有效期
127.0.0.1:6379> ttl age
(integer) -1

例子: 重新设置key的过期时间

EXPIRE

127.0.0.1:6379> EXPIRE name 1000 
(integer) 1

例子: 永远不过期

PERSIST

127.0.0.1:6379> PERSIST name (integer) 1

列表list

image-20240708003450475

列表是一个双向可读写的管道,其头部是左侧,尾部是右侧,一个列表最多可以包含2^32-1(4294967295)个元素,下标 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,元素值可以重复,常用于存入日志等场景,此数据类型比较常用

抢单机制 放出20单, 加入购物车就 卡单 成交划走一单

  • 有序
  • 可重复
  • 左右都可以操作

生成列表并插入数据

image-20240708003534011

image-20240708003539100

命令 解释 例子
lpush 从左边添加数据 例子:lpush name zhou wu zheng wang
rpush 从右边添加数据 例子: rpush car benz bmw
llen 获取列表长度 例子: llen 列表名称
lindex 获取单个元数 例子: lindex name 0 ; lindex name -1
lrange 获取多个元素 例子: lrange name 0 3 第1个到第三个元素
lset 修改列表元素 例子: lset name 2 feng 将name的第二个元素改为feng
lpop 删除列表元素 例子: lpop name 删除左边第一个
rpop 删除列表元素 例子: rpop name 删除右边第一个
ltrim 对列表修剪, 例子: ltrim name 1 2 只留下编号为 1 2 的文件
del 删除列表 例子:del name

LPUSH和RPUSH都可以插入列表

LPUSHkeyvalue [value …]
时间复杂度: O(1)
将一个或多个值 value 插入到列表 key 的表头

如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头:比如说,对空列表
mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a ,这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。

如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。当 key 存在但不是列表类型时,返回一个错误。

RPUSH key value [value …]
时间复杂度: O(1)
将一个或多个值 value 插入到列表 key 的表尾(最右边)

如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾:比如对一个空列表 mylist 执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、
RPUSH mylist b 、 RPUSH mylist c 。

如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。当 key 存在但不是列表类型时,返回一个错误。

例子:新建列表

#从左边添加数据,已添加的需向右移
127.0.0.1:6379>  lpush name zhou wu zheng wang   #根据顺序逐个写入name,最后的wang会在列表的最左侧。
(integer) 4
127.0.0.1:6379> type name
list
  
#从右边加 数据
127.0.0.1:6379>  rpush name zhou wu zheng wang

例子: 获取列表中的元素

127.0.0.1:6379> lindex name 0
"wang"
127.0.0.1:6379> lindex name 1
"zheng"
127.0.0.1:6379> lindex name 2
"wu"
127.0.0.1:6379> lindex name 3
"zhou"

集合 **set **

image-20240708143442690

Set 是 String 类型的无序集合,集合中的成员是唯一的,这就意味着集合中不能出现重复的数据,可以在两个不同的集合中对数据进行对比并取值,常用于取值判断,统计,交集等场景,例如: 实现共同的朋友,微信好友,qq好友

集合特点

  • 无序
  • 无重复
  • 集合间操作

生成集合key

127.0.0.1:6379> SADD set1 v1
(integer) 1
127.0.0.1:6379> SADD set2 v2 v4
(integer) 2
127.0.0.1:6379> TYPE set1
set
127.0.0.1:6379> TYPE set2
set

追加数值

#追加时,只能追加不存在的数据,不能追加已经存在的数值
127.0.0.1:6379> SADD set1 v2 v3 v4
(integer) 3
127.0.0.1:6379> SADD set1 v2 #已存在的value,无法再次添加
(integer) 0
127.0.0.1:6379> TYPE set1
set
127.0.0.1:6379> TYPE set2
set

查看集合的所有数据

127.0.0.1:6379> SMEMBERS set1
1) "v4"
2) "v1"
3) "v3"
4) "v2"
127.0.0.1:6379> SMEMBERS set2
1) "v4"
2) "v2"

删除集合中的元素

127.0.0.1:6379> sadd goods mobile laptop car 
(integer) 3
127.0.0.1:6379> srem goods car
(integer) 1
127.0.0.1:6379> SMEMBERS goods
1) "mobile"
2) "laptop"
127.0.0.1:6379

集合间操作

image-20240708150225657

获取集合的交集

交集:已属于A且属于B的元素称为A与B的交(集)

127.0.0.1:6379> SINTER set1 set2
1) "v4"
2) "v2"

获取集合的并集

并集:已属于A或属于B的元素为称为A与B的并(集)

127.0.0.1:6379> SUNION set1 set2
1) "v2"
2) "v4"
3) "v1"
4) "v3"

获取集合的差集

差集:已属于A而不属于B的元素称为A与B的差(集)

127.0.0.1:6379> SDIFF set1 set2
1) "v1"
2) "v3"

有序集合 sorted set

Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员,不同的是每个元素都会关联一个double(双精度浮点型)类型的分数,redis正是通过该分数来为集合中的成员进行从小到大的排序,有序集合的成员是唯一的,但分数(score)却可以重复,集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1), 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员),经常用于排行榜的场景

image-20240708150441898

有序集合特点

  • 有序
  • 无重复元素
  • 每个元素是由score和value组成
  • score 可以重复
  • value 不可以重复

生成有序集合

127.0.0.1:6379> ZADD zset1 1 v1  #分数为1
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v2
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v3  #分数可重复,元素值不可以重复(integer) 1
127.0.0.1:6379> ZADD zset1 3 v4
(integer) 1
127.0.0.1:6379> TYPE zset1
zset
127.0.0.1:6379> TYPE zset2
zset



#一次生成多个数据:
127.0.0.1:6379> ZADD zset2 1 v1 2 v2 3 v3 4 v4 5 v5 (integer) 5

有序集合实现排行榜

127.0.0.1:6379> ZADD paihangbang 90 nezha 199 zhanlang 60 zhuluoji 30 gangtiexia 
(integer) 4


27.0.0.1:6379> ZRANGE paihangbang 0 -1  #正序排序后显示集合内所有的key,score从小到大显示
1) "gangtiexia"
2) "zhuluoji"
3) "nezha"
4) "zhanlang"


27.0.0.1:6379> ZREVRANGE paihangbang 0  -1#倒序排序后显示集合内所有的key,score从大到小显示
1) "zhanlang"
2) "nezha"
3) "zhuluoji"
4) "gangtiexia"



127.0.0.1:6379> ZRANGE paihangbang 0  -1 WITHSCORES  #正序显示指定集合内所有key和得分情况
1) "gangtiexia"
2) "30"
3) "zhuluoji"
4) "60"
5) "nezha"
6) "90"
7) "zhanlang"

获取集合的个数

127.0.0.1:6379> ZCARD paihangbang (integer) 4
127.0.0.1:6379> ZCARD zset1
(integer) 4
127.0.0.1:6379> ZCARD zset2
(integer) 4

基于索引返回数值

127.0.0.1:6379> ZRANGE paihangbang 02
1) "gangtiexia"
2) "zhuluoji"
3) "nezha"
127.0.0.1:6379> ZRANGE paihangbang 010  #超出范围不报错1) "gangtiexia"
2) "zhuluoji"
3) "nezha"
4) "zhanlang"
127.0.0.1:6379> ZRANGE zset1 13
1) "v2"
2) "v3"
3) "v4"
127.0.0.1:6379> ZRANGE zset1 02
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> ZRANGE zset1 22
1) "v3"

返回某个数值的索引(排名)

127.0.0.1:6379> ZADD paihangbang 90 nezha 199 zhanlang 60 zhuluoji 30 gangtiexia (integer) 4
127.0.0.1:6379> ZRANK paihangbang zhanlang
(integer) 3   #第4个
127.0.0.1:6379> ZRANK paihangbang zhuluoji
(integer) 1   #第2个

获取分数

127.0.0.1:6379> zscore paihangbang gangtiexia "30"

删除元素

127.0.0.1:6379> ZADD paihangbang 90 nezha 199 zhanlang 60 zhuluoji 30 gangtiexia (integer) 4
127.0.0.1:6379> ZRANGE paihangbang 0-1
1) "gangtiexia"
2) "zhuluoji"
3) "nezha"
4) "zhanlang"
127.0.0.1:6379> ZREM paihangbang zhuluoji zhanlang
(integer) 2
127.0.0.1:6379> ZRANGE paihangbang 0-1
1) "gangtiexia"
2) "nezha"

哈希hash

hash 即字典, 是一个string类型的字段(field)和值(value)的映射表,Redis 中每个 hash 可以存储 2^32 -1 键值对,类似于字典,存放了多个k/v 对,hash特别适合用于存储对象场景

image-20240708151949312

image-20240708151957091

image-20240708152002670

生成 hash key

格式:

HSEThashfield value
时间复杂度: O(1)
将哈希表 hash 中域 field 的值设置为 value 。
如果给定的哈希表并不存在,那么一个新的哈希表将被创建并执行 HSET 操作。如果域 field 已经存在于哈希表中,那么它的旧值将被新值 value 覆盖。

例子:

127.0.0.1:6379> HSET 9527 name zhouxingxing age 20 (integer) 2
127.0.0.1:6379> TYPE 9527
hash
#查看所有字段的值
127.0.0.1:6379> hgetall 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "20"


#增加字段
127.0.0.1:6379> HSET 9527 gender male (integer) 1
127.0.0.1:6379> hgetall 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "20"
5) "gender"
6) "male"

获取hash key的对应字段的值

127.0.0.1:6379> HGET 9527 name
"zhouxingxing"
127.0.0.1:6379> HGET 9527 age
"20"
127.0.0.1:6379> HMGET 9527 name age  #获取多个值
1) "zhouxingxing"
2) "20"
127.0.0.1:6379>

删除一个hash key的对应字段

127.0.0.1:6379> HDEL 9527 age
(integer) 1
127.0.0.1:6379> HGET 9527 age
(nil)
127.0.0.1:6379> hgetall 9527
1) "name"
2) "zhouxingxing"
127.0.0.1:6379> HGET 9527 name
"zhouxingxing"

批量设置hash key的多个field和value

127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong
OK
127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "50"
5) "city"
6) "hongkong"

获取hash中指定字段的值

127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong
OK
127.0.0.1:6379> HMGET 9527 name age 
1) "zhouxingxing"
2) "50"
127.0.0.1:6379>

获取hash中的所有字段名field

127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong #重新设置
OK
127.0.0.1:6379> HKEYS 9527
1) "name"
2) "age"
3) "city"

获取hash key对应所有field的value

127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong
OK
127.0.0.1:6379> HVALS 9527
1) "zhouxingxing"
2) "50"
3) "hongkong"

获取指定hash key的所有field及value

127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "50"
5) "city"
6) "hongkong"
127.0.0.1:6379>

删除 hash

127.0.0.1:6379> DEL 9527
(integer) 1
127.0.0.1:6379> HMGET 9527 name city
1) (nil)
2) (nil)
127.0.0.1:6379> EXISTS 9527
(integer) 0

redis主从复制和哨兵模式

redis主从复制

主从复制过程

Redis主从复制分为全量同步和增量同步

主从复制配置

1.准备环境
确保已经安装了 Redis 服务,并且主从服务器之间网络连接正常。
[root@localhost ~]# yum install redis -y
2.主服务器配置
在主服务器的 Redis 配置文件(通常是 redis.conf )中,无需做特殊的主从复制相关配置,保持默认即可。但需要确保主服务器的监听地址是可访问的。
3.从服务器配置
在从服务器的 Redis 配置文件中,添加以下配置:
slaveof <master_ip> <master_port>:
指定主服务器的 IP 地址和端口。#在266行
例如:slaveof 192.168.10.10 6379
4.启动主从服务器
分别启动主服务器和从服务器。
5.验证配置
连接到从服务器,执行 INFO replication 命令,可以查看主从复制的相关信息,确认复制状态是否正常。
[root@localhost ~]# redis-cli 
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.10.10
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1721033309
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
全量复制过程

image-20240708233138253

首次主从同步是全量同步,主从同步可以让从服务器从主服务器同步数据,而且从服务器还可再有其它的从服务器,即另外一台redis服务器可以从一台从服务器进行数据同步,redis 的主从同步是非阻塞的,master收到从服务器的psync(2.8版本之前是SYNC)命令,会fork一个子进程在后台执行bgsave命令,并将新写入的数据写入到一个缓冲区中,bgsave执行完成之后,将生成的RDB文件发送给slave,然后master再将缓冲区的内容以redis协议格式再全部发送给slave,slave 先删除旧数据,slave将收到后的RDB文件载入自己的内存,再加载所有收到缓冲区的内容 从而这样一次完整的数据同步Redis全量复制一般发生在Slave首次初始化阶段,这时Slave需要将Master上的所有数据都复制一份。

增量复制过程

image-20240708233204460

全量同步之后再次需要同步时,从服务器只要发送当前的offset位置(等同于MySQL的binlog的位置)给主服务器,然后主服务器根据相应的位置将之后的数据(包括写在缓冲区的积压数据)发送给从服务器,再次将其保存到从节点内存即可。

主从同步完整过程

具体主从同步过程如下:

1)从服务器连接主服务器,发送PSYN(同步)C命令
2)主服务器接收到PSYNC命令后,开始执行BGSAVE命令生成RDB快照文件并使用缓冲区记录此后执行的所有写命令
3)主服务器BGSAVE执行完后,向所有从服务器发送RDB快照文件,并在发送期间继续记录被执行的写命令
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照至内存
5)主服务器快照发送完毕后,开始向从服务器发送缓冲区中的写命令
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令
7)后期同步会先发送自己slave_repl_offset位置,只同步新增加的数据,不再全量同步

image-20240708233257352

image-20240708233321398

image-20240708233355957

复制缓冲区(环形队列)配置参数:

#复制缓冲区大小,建议要设置足够大
repl-backlog-size 1mb 

#Redis同时也提供了当没有slave需要同步的时候,多久可以释放环形队列:  
repl-backlog-ttl   3600   #最长保持时间  3600秒
避免全量复制
  • 第一次全量复制不可避免,后续的全量复制可以利用小主节点(内存小),业务低峰时进行全量
  • 节点运行ID不匹配:主节点重启会导致RUNID变化,可能会触发全量复制,可以利用故障转移,例如哨兵或集群,而从节点重启动,不会导致全量复制
  • 复制积压缓冲区不足: 当主节点生成的新数据大于缓冲区大小,从节点恢复和主节点连接后,会导致全量复制.解决方法将repl-backlog-size 调大
避免复制风暴
  • 单主节点复制风暴

当主节点重启,多从节点复制

解决方法:更换复制拓扑

image-20240708233538860

  • 单机器多实例复制风暴

机器宕机后,大量全量复制

解决方法:主节点分散多机器

image-20240708233559465

主从同步优化配置

Redis在2.8版本之前没有提供增量部分复制的功能,当网络闪断或者slave Redis重启之后会导致主从之间的全量同步,即从2.8版本开始增加了部分复制的功能。

性能相关配置

repl-diskless-sync no # 是否使用无盘同步RDB文件,默认为no,no为不使用无盘,需要将RDB文件保存到磁盘后再发送给slave,yes为支持无盘,支持无盘就是RDB文件不需要保存至本地磁盘,而且直接通过socket文件发送给slave

repl-diskless-sync-delay 5 #diskless时复制的服务器等待的延迟时间

repl-ping-slave-period 10 #slave端向server端发送ping的时间间隔,默认为10秒

repl-timeout 60 #设置主从ping连接超时时间,超过此值无法连接,master_link_status显示为down,并记录错误日志

repl-disable-tcp-nodelay no #是否启用TCP_NODELAY,如设置成yes,则redis会合并小的TCP包从而节省带宽, 但会增加同步延迟(40ms),造成master与slave数据不一致,假如设置成no,则redis master会立即发送同步数据,没有延迟,yes关注网络性能,no关注redis服务中的数据一致性


repl-backlog-size 1mb #master的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式:repl-backlog-size = 允许从节点最大中断时长 * 主实例offset每秒写入量,比如master每秒最大写入64mb,最大允许60秒,那么就要设置为64mb*60秒=3840MB(3.8G),建议此值是设置的足够大

repl-backlog-ttl 3600 #3600秒   如果一段时间后没有slave连接到master,则backlog size的内存将会被释放。如果值为0则 表示永远不释放这部份内存。

slave-priority 100 #slave端的优先级设置,值是一个整数,数字越小表示优先级越高。当master故障时将会按照优先级来选择slave端进行恢复,如果值设置为0,则表示该slave永远不会被选择。

min-replicas-to-write 1 #设置一个master的可用slave不能少于多少个,否则master无法执行写

min-slaves-max-lag 20 #设置至少有上面数量的slave延迟时间都大于多少秒时,master不接收写操作(拒绝写入)

常见主从复制故障汇总

master密码不对

即配置的master密码不对,导致验证不通过而无法建立主从同步关系。

[root@centos7 ~]#tail -f /var/log/redis/redis.log 
24930:S 20 Feb 2020 13:53:57.029 * Connecting to MASTER 10.0.0.8:6379
24930:S 20 Feb 2020 13:53:57.030 * MASTER <-> REPLICA sync started
24930:S 20 Feb 2020 13:53:57.030 * Non blocking connect for SYNC fired the 
event.
24930:S 20 Feb 2020 13:53:57.030 * Master replied to PING, replication can 
continue...
24930:S 20 Feb 2020 13:53:57.031 # Unable to AUTH to MASTER: -ERR invalid 
password

Redis版本不一致

不同的redis 大版本之间存在兼容性问题,比如:3和4,4和5之间,因此各master和slave之间必须保持版本一致

image-20240708233921557

无法远程连接

在开启了安全模式情况下,没有设置bind地址或者密码

[root@localhost ~]# redis-cli  -h 192.168.91.100
192.168.91.100:6379> info
DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.

配置不一致

主从节点的maxmemory不一致,主节点内存大于从节点内存,主从复制可能丢失数据rename-command 命令不一致,如在主节点定义了fushall,flushdb,从节点没定义,结果执行flushdb,不同步

#master有一个rename-command flushdb "magedu",而slave没有这个配置,则同步时从节点可以看到
以下同步错误
3181:S 21 Oct 2020 17:34:50.581 # == CRITICAL == This replica is sending an 
error to its master: 'unknown command `magedu`, with args beginning with: ' after 
processing the command '<unknown>'

哨兵模式

redis集群介绍

主从架构无法实现master和slave角色的自动切换,即当master出现redis服务异常、主机断电、磁盘损坏等问题导致master无法使用,而redis主从复制无法实现自动的故障转移(将slave 自动提升为新master),需要手动修改环境配置,才能切换到slave redis服务器,另外当单台Redis服务器性能无法满足业务写入需求的时候,也无法横向扩展Redis服务的并行写入性能

需要解决以上的两个核心问题:

  • master和slave角色的无缝切换,让业务无感知从而不影响业务使用
  • 可横向动态扩展Redis服务器,从而实现多台服务器并行写入以实现更高并发的目的。

Redis 集群实现方式:

  • 客户端分片: 由应用决定将不同的KEY发送到不同的Redis服务器
  • 代理分片: 由代理决定将不同的KEY发送到不同的Redis服务器,代理程序如:codis,twemproxy等
  • Redis Cluster

哨兵 (Sentinel)工作原理

sentinel架构和故障转移

image-20240709001334113

Sentinel 架构

image-20240709001349464

Sentinel 故障转移

image-20240709001416464

Sentinel 进程是用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障的时候,可以实现Master和Slave服务器的切换,保证系统的高可用,此功能在redis2.6+的版本已引用,Redis的哨兵模式到了2.8版本之后就稳定了下来。一般在生产环境也建议使用Redis的2.8版本的以后版本

哨兵(Sentinel) 是一个分布式系统,可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossip protocols)来接收关于Master主服务器是否下线的信息,并使用投票协议(Agreement Protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master

每个哨兵(Sentinel)进程会向其它哨兵(Sentinel)、Master、Slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定配置时间(此项可配置)内未得到回应,则暂时认为对方已离线,也就是所谓的”主观认为宕机” (主观:是每个成员都具有的独自的而且可能相同也可能不同的意识),英文名称:Subjective Down,简称SDOWN

有主观宕机,对应的有客观宕机。当“哨兵群”中的多数Sentinel进程在对Master主服务器做出SDOWN 的判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,这种方式就是“客观宕机”(客观:是不依赖于某种意识而已经实际存在的一切事物),英文名称是:Objectively Down, 简称 ODOWN

通过一定的vote算法,从剩下的slave从服务器节点中,选一台提升为Master服务器节点,然后自动修改相关配置,并开启故障转移(failover)

Sentinel 机制可以解决master和slave角色的自动切换问题,但单个 Master 的性能瓶颈问题无法解决,类似于MySQL中的MHA功能

Redis Sentinel中的Sentinel节点个数应该为大于等于3且最好为奇数

客户端初始化时连接的是Sentinel节点集合,不再是具体的Redis节点,但Sentinel只是配置中心不是代理。

Redis Sentinel 节点与普通redis 没有区别,要实现读写分离依赖于客户端程序

redis 3.0 之前版本中,生产环境一般使用哨兵模式,3.0后推出redis cluster功能,可以支持更大规模的生产环境

sentinel中的三个定时任务

  • 每10秒每个sentinel对master和slave执行info

​ 发现slave节点

​ 确认主从关系

  • 每2秒每个sentinel通过master节点的channel交换信息(pub/sub)

​ 通过sentinel__:hello频道交互

​ 交互对节点的“看法”和自身信息

  • 每1秒每个sentinel对其他sentinel和redis执行ping

实现哨兵

image-20240709001637653

3.2.3.1 哨兵的准备实现主从复制架构

哨兵的前提是已经实现了一个redis的主从复制的运行环境,从而实现一个一主两从基于哨兵的高可用

redis架构

注意: master 的配置文件中masterauth 和slave 都必须相同

所有主从节点的redis.conf中关健配置

范例: 准备主从环境配置

安装redis略

先实现主从复制


#在所有主从节点执行
[root@centos7  ~]#vim /etc/redis.conf
bind 0.0.0.0
masterauth "123456"
requirepass "123456"



#或者非交互执行
[root@centos8 ~]#sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e 's/^# masterauth .*/masterauth 123456/' -e 's/^# requirepass .*/requirepass 123456/'  /etc/redis.conf



echo  >>   "masterauth "123456"   
echo  >>   "requirepass "123456"


#在所有从节点执行
[root@centos8 ~]#echo "replicaof 192.168.91.100 6379" >> /etc/redis.conf
#在所有主从节点执行
[root@centos8 ~]#systemctl enable --now redis



**** 编辑哨兵的配置文件

sentinel配置

Sentinel实际上是一个特殊的redis服务器,有些redis指令支持,但很多指令并不支持.默认监听在26379/tcp端口.

哨兵可以不和Redis服务器部署在一起,但一般部署在一起以节约成本

所有redis节点使用相同的以下示例的配置文件

#如果是编译安装,在源码目录有sentinel.conf,复制到安装目录即可,
如:/apps/redis/etc/sentinel.conf


[root@centos7 ~]#vim /etc/redis-sentinel.conf 
bind 0.0.0.0   #修改监听端口 
port 26379     #不用修改默认
daemonize yes  # 不用修改如果是systemd 启动模式, 修改后启动不了
pidfile "/apps/resdis/run/redis-sentinel.pid"  #指定pid文件
logfile "/apps/redis/log/sentinel_26379.log"  # 指定日志文件
dir "/tmp"  #工作目录不用修改



sentinel monitor mymaster 10.0.0.8 6379 2
#mymaster是集群的名称,此行指定当前mymaster集群中master服务器的地址和端口
#2为法定人数限制(quorum),即有几个sentinel认为master down了就进行故障转移,一般此值是所有sentinel节点(一般总数是>=3的 奇数,如:3,5,7等)的一半以上的整数值,比如,总数是3,即3/2=1.5,取整为2,是master的ODOWN客观下线的依据


sentinel auth-pass mymaster 123456
#mymaster集群中master的密码,注意此行要在上面行的下面

sentinel down-after-milliseconds mymaster 30000
#(SDOWN)判断mymaster集群中所有节点的主观下线的时间,    单位:毫秒,建议3000(3秒) 否则等待时间过长

sentinel parallel-syncs mymaster 1
#发生故障转移后,可以同时向新master同步数据的slave的数量,数字越小总同步时间越长,但可以减轻新master的负载压力

sentinel failover-timeout mymaster 180000
#所有slaves指向新的master所需的超时时间,单位:毫秒

sentinel deny-scripts-reconfig yes #禁止修改脚本



修改文件内容

[root@localhost etc]#grep -vE "^#|^$"  sentinel.conf 
bind 0.0.0.0
port 26379
daemonize  yes
pidfile /apps/redis/run/redis-sentinel.pid
logfile "/apps/redis/log/sentinel.log"
dir /tmp
sentinel monitor mymaster 192.168.91.100 6379 2
sentinel auth-pass  mymaster  123456
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes

准备service 文件 **注意先开 主再开从 ** 全部节点都需要

[root@localhost etc]#cat  >> /lib/systemd/system/redis-sentinel.service  <<eof
[Unit]
Description=Redis Sentinel
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
eof


[root@localhost etc]# systemctl daemon-reload 
[root@localhost etc]# systemctl start redis-sentinel.service

关掉 主服务器验证

在主上观察日志

[root@localhost etc]# tail -f /apps/redis/log/sentinel.log
395:X 09 Jul 2024 01:23:29.630 * +sentinel sentinel f24295730ef1a3dc3395a32380f26df3aa08fd38 192.168.91.100 26379 @ mymaster 192.168.91.100 6379
8395:X 09 Jul 2024 01:23:31.014 * +sentinel sentinel 114478912af9bd3d63ae07ae0b6f288564f40140 192.168.91.101 26379 @ mymaster 192.168.91.100 6379

#先sdown  再 odown
8395:X 09 Jul 2024 01:29:25.631 # +sdown master mymaster 192.168.91.100 6379
8395:X 09 Jul 2024 01:29:25.722 # +odown master mymaster 192.168.91.100 6379 #quorum 2/2



8395:X 09 Jul 2024 01:29:25.722 # +new-epoch 1
8395:X 09 Jul 2024 01:29:25.722 # +try-failover master mymaster 192.168.91.100 6379
8395:X 09 Jul 2024 01:29:25.724 # +vote-for-leader 177dbc2f08df08a97cd69a4b4142870a38a3cb77 1
8395:X 09 Jul 2024 01:29:25.725 # f24295730ef1a3dc3395a32380f26df3aa08fd38 voted for f24295730ef1a3dc3395a32380f26df3aa08fd38 1

哨兵模式查看状态以及报错

在sentinel状态中尤其是最后一行,涉及到masterIP是多少,有几个slave,有几个sentinels,必须是符合全部服务器数量

[root@redis-master ~]#redis-cli -p 26379
127.0.0.1:26379> 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=10.0.0.8:6379,slaves=2,sentinels=3 #两个slave,三个sentinel服务器,如果sentinels值不符合,检查myid可能冲突


###  去看  配置文件中的 id  要所有节点不一样
[root@localhost etc]#tail -f  /apps/redis/etc/sentinel.conf 
# Generated by CONFIG REWRITE
maxclients 4064
protected-mode no
supervised systemd
sentinel leader-epoch mymaster 1
sentinel known-replica mymaster 192.168.91.100 6379
sentinel known-replica mymaster 192.168.91.102 6379
sentinel known-sentinel mymaster 192.168.91.101 26379 114478912af9bd3d63ae07ae0b6f288564f40140
sentinel known-sentinel mymaster 192.168.91.102 26379 177dbc2f08df08a97cd69a4b4142870a38a3cb71
sentinel current-epoch 1

主再恢复后会变成从

[root@localhost etc]#systemctl start redis
[root@localhost etc]#redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.91.101
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:134979
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:473c28e4bd1fcf189af91222aaed0d2c235f32aa
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:134979
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:133670
repl_backlog_histlen:1310

Redis Cluster(Redis集群)

Redis Cluster** 工作原理

在哨兵sentinel机制中,可以解决redis高可用问题,即当master故障后可以自动将slave提升为master,从而可以保证redis服务的正常使用,但是无法解决redis单机写入的瓶颈问题,即单机redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素。

为了解决单机性能的瓶颈,提高Redis 性能,可以使用分布式集群的解决方案

早期Redis 分布式集群部署方案:

  1. 客户端分区:由客户端程序决定key写分配和写入的redis node,但是需要客户端自己实现写入分配、高可用管理和故障转移等
  2. 代理方案:基于三方软件实现redis proxy,客户端先连接之代理层,由代理层实现key的写入分配,对客户端来说是有比较简单,但是对于集群管节点增减相对比较麻烦,而且代理本身也是单点和性能瓶颈。

redis 3.0版本之后推出了无中心架构的redis cluster机制,在无中心的redis集群当中,其每个节点保存当前节点数据和整个集群状态,每个节点都和其他所有节点连接

Redis Cluster****特点如下:

  1. 所有Redis节点使用(PING机制)互联
  2. 集群中某个节点的是否失效,是由整个集群中超过半数的节点监测都失效,才能算真正的失效
  3. 客户端不需要proxy即可直接连接redis,应用程序中需要配置有全部的redis服务器IP
  4. redis cluster把所有的redis node 平均映射到 0-16383个槽位(slot)上,读写需要到指定的redis node上进行操作,因此有多少个redis node相当于redis 并发扩展了多少倍,每个redis node 承担16384/N个槽位
  5. Redis cluster预先分配16384个(slot)槽位,当需要在redis集群中写入一个key -value的时候,会使用CRC16(key) mod 16384之后的值,决定将key写入值哪一个槽位从而决定写入哪一个Redis节点上,从而有效解决单机瓶颈。

Redis cluster架构

image-20240709155620106

Redis cluster基本架构

假如三个主节点分别是:A, B, C 三个节点,采用哈希槽 (hash slot)的方式来分配16384个slot 的话它们三个节点分别承担的slot 区间可以是:

节点A覆盖 05460
节点B覆盖 546110922
节点C覆盖 1092316383

image-20240709155657851

Redis cluster主从架构

Redis cluster的架构虽然解决了并发的问题,但是又引入了一个新的问题,每个Redis master的高可用

如何解决?那就是对每个master 节点都实现主从复制,从而实现 redis 高可用性

image-20240709155731025

Redis Cluster部署架构说明

环境A:3台服务器,每台服务器启动6379和6380两个redis 服务实例,适用于测试环境

image-20240709155824589

环境B:6台服务器,分别是三组master/slave,适用于生产环境

image-20240709155848937

部署方式介绍

redis cluster 有多种部署方法

  • 原生命令安装

    理解Redis Cluster架构

    生产环境不使用

  • 官方工具安装

    高效、准确

    生产环境可以使用

  • 自主研发

    可以实现可视化的自动化部署

实现集群

开启多实例 来实现redis

redis的集群一般需要6个节点,3主3从。方便起见,这里所有节点在同一台服务器上模拟:
以端口号进行区分:3个主节点端口号:6001/6002/6003,对应的从节点端口号:6004/6005/6006

但是可能随机搭配

新建集群文件目录
[root@localhost src]#cd  /apps/redis/
[root@localhost redis]#mkdir -p redis-cluster/redis600{1..6}
准备可执行文件到每个文件夹
for i in {1..6}
do
cp /data/redis-5.0.7/redis.conf /apps/redis/redis-cluster/redis600$i
cp /data/redis-5.0.7/src/redis-cli /data/redis-5.0.7/src/redis-server /apps/redis/redis-cluster/redis600$i
done

[root@localhost redis-cluster]#tree
.
├── redis6001
│   ├── redis-cli
│   ├── redis.conf
│   └── redis-server
├── redis6002
│   ├── redis-cli
│   ├── redis.conf
│   └── redis-server
├── redis6003
│   ├── redis-cli
│   ├── redis.conf
│   └── redis-server
├── redis6004
│   ├── redis-cli
│   ├── redis.conf
│   └── redis-server
├── redis6005
│   ├── redis-cli
│   ├── redis.conf
│   └── redis-server
└── redis6006
    ├── redis-cli
    ├── redis.conf
    └── redis-server

6 directories, 18 files

开启群集功能
#其他5个文件夹的配置文件以此类推修改,注意6个端口都要不一样。
[root@localhost redis6001]#cd /apps/redis/redis-cluster/redis6001/
vim redis.conf
#bind 127.0.0.1							#69行,注释掉bind 项,默认监听所有网卡
protected-mode no						#88行,修改,关闭保护模式
port 6001								#92行,修改,redis监听端口,
daemonize yes							#136行,开启守护进程,以独立进程启动  如果是 systemd 启动不需要修改
cluster-enabled yes						#832行,取消注释,开启群集功能
cluster-config-file nodes-6001.conf		#840行,取消注释,群集名称文件设置
cluster-node-timeout 15000				#846行,取消注释群集超时时间设置
appendonly yes							#700行,修改,开启AOF持久化



[root@localhost redis6001]#sed -i.bak  's/bind 127.0.0.1/bind 0.0.0.0/' redis.conf 
[root@localhost redis6001]#sed -i.bak  's/protected-mode yes/protected-mode no/' redis.conf 
[root@localhost redis6001]#sed -i.bak  's/^port .*/port 6001/' redis.conf
[root@localhost redis6001]#sed -i.bak  's/^daemonize .*/daemonize yes/' redis.conf 
[root@localhost redis6001]#sed -i.bak  's/^# cluster-enabled .*/cluster-enabled yes/' redis.conf 
[root@localhost redis6001]#sed -i.bak  's/^# cluster-config-file .*/cluster-config-file nodes-6001.conf/' redis.conf 
[root@localhost redis6001]#sed -i.bak  's/^# cluster-node-timeout .*/cluster-node-timeout 15000/' redis.conf
[root@localhost redis6001]#sed -i.bak  's/appendonly no/appendonly yes/' redis.conf



[root@localhost redis6001]#cd /apps/redis/redis-cluster/redis6001
#先切换目录
#复制配置文件
for i in {2..6}
do
\cp -f  ./redis.conf   /apps/redis/redis-cluster/redis600${i}
done



sed -i.bak -e 's/bind 127.0.0.1/bind 0.0.0.0/'   -e 's/protected-mode yes/protected-mode no/' -e  's/^port .*/port 6002/' -e 's/^daemonize .*/daemonize yes/' -e  's/^# cluster-enabled .*/cluster-enabled yes/'  -e 's/^# cluster-config-file .*/cluster-config-file nodes-6002.conf/' -e 's/^# cluster-node-timeout .*/cluster-node-timeout 15000/' -e 's/appendonly no/appendonly yes/' ../redis6002/redis.conf



sed  -i   's/6001/6002/'   /apps/redis/redis-cluster/redis6002/redis.conf
sed  -i   's/6001/6003/'   /apps/redis/redis-cluster/redis6003/redis.conf
sed  -i   's/6001/6004/'   /apps/redis/redis-cluster/redis6004/redis.conf
sed  -i   's/6001/6005/'   /apps/redis/redis-cluster/redis6005/redis.conf
sed  -i   's/6001/6006/'   /apps/redis/redis-cluster/redis6006/redis.conf



sed -i.bak -e 's/bind 127.0.0.1/bind 0.0.0.0/'   -e 's/protected-mode yes/protected-mode no/' -e  's/^port .*/port 6003/' -e 's/^daemonize .*/daemonize yes/' -e  's/^# cluster-enabled .*/cluster-enabled yes/'  -e 's/^# cluster-config-file .*/cluster-config-file nodes-6003.conf/' -e 's/^# cluster-node-timeout .*/cluster-node-timeout 15000/' -e 's/appendonly no/appendonly yes/' ../redis6003/redis.conf

sed -i.bak -e 's/bind 127.0.0.1/bind 0.0.0.0/'   -e 's/protected-mode yes/protected-mode no/' -e  's/^port .*/port 6004/' -e 's/^daemonize .*/daemonize yes/' -e  's/^# cluster-enabled .*/cluster-enabled yes/'  -e 's/^# cluster-config-file .*/cluster-config-file nodes-6004.conf/' -e 's/^# cluster-node-timeout .*/cluster-node-timeout 15000/' -e 's/appendonly no/appendonly yes/' ../redis6004/redis.conf


sed -i.bak -e 's/bind 127.0.0.1/bind 0.0.0.0/'   -e 's/protected-mode yes/protected-mode no/' -e  's/^port .*/port 6005/' -e 's/^daemonize .*/daemonize yes/' -e  's/^# cluster-enabled .*/cluster-enabled yes/'  -e 's/^# cluster-config-file .*/cluster-config-file nodes-6005.conf/' -e 's/^# cluster-node-timeout .*/cluster-node-timeout 15000/' -e 's/appendonly no/appendonly yes/' ../redis6005/redis.conf


sed -i.bak -e 's/bind 127.0.0.1/bind 0.0.0.0/'   -e 's/protected-mode yes/protected-mode no/' -e  's/^port .*/port 6006/' -e 's/^daemonize .*/daemonize yes/' -e  's/^# cluster-enabled .*/cluster-enabled yes/'  -e 's/^# cluster-config-file .*/cluster-config-file nodes-6006.conf/' -e 's/^# cluster-node-timeout .*/cluster-node-timeout 15000/' -e 's/appendonly no/appendonly yes/' ../redis6006/redis.conf
启动redis节点

分别进入那六个文件夹,执行命令:redis-server redis.conf ,来启动redis节点

[root@localhost redis6001]#systemctl stop redis
# 先停止之前的服务
[root@localhost redis6001]#ss -natp |grep 6379

[root@localhost redis6001]#cd /etc/redis/redis-cluster/redis6001
# 切换目录
[root@localhost redis6001]#redis-server redis.conf
# 启动


#脚本去启动
for d in {1..6}
do
cd /apps/redis/redis-cluster/redis600$d
redis-server redis.conf
done
查看是否启动成功
[root@localhost redis6006]#ps -ef | grep redis
root      24465      1  0 23:57 ?        00:00:00 redis-server 0.0.0.0:6001 [cluster]
root      24467      1  0 23:57 ?        00:00:00 redis-server 0.0.0.0:6002 [cluster]
root      24475      1  0 23:57 ?        00:00:00 redis-server 0.0.0.0:6003 [cluster]
root      24480      1  0 23:57 ?        00:00:00 redis-server 0.0.0.0:6004 [cluster]
root      24485      1  0 23:57 ?        00:00:00 redis-server 0.0.0.0:6005 [cluster]
root      24490      1  0 23:57 ?        00:00:00 redis-server 0.0.0.0:6006 [cluster]
root      24505  18792  0 23:58 pts/11   00:00:00 grep --color=auto redis


[root@localhost redis6006]#ss -natp |grep "\b600[1-6]\b"
LISTEN     0      128          *:6001                     *:*                   users:(("redis-server",pid=24465,fd=6))
LISTEN     0      128          *:6002                     *:*                   users:(("redis-server",pid=24467,fd=6))
LISTEN     0      128          *:6003                     *:*                   users:(("redis-server",pid=24475,fd=6))
LISTEN     0      128          *:6004                     *:*                   users:(("redis-server",pid=24480,fd=6))
LISTEN     0      128          *:6005                     *:*                   users:(("redis-server",pid=24485,fd=6))
LISTEN     0      128          *:6006                     *:*                   users:(("redis-server",pid=24490,fd=6))

启动集群
[root@localhost redis6006]#redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1
#六个实例分为三组,每组一主一从,前面的做主节点,后面的做从节点。下面交互的时候 需要输入 yes 才可以创建。
--replicas 1 表示每个主节点有1个从节点。



[root@localhost redis6006]#redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:6005 to 127.0.0.1:6001
Adding replica 127.0.0.1:6006 to 127.0.0.1:6002
Adding replica 127.0.0.1:6004 to 127.0.0.1:6003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 8bf8e2e6d2c180acbc06dc9554a56f2a4755f004 127.0.0.1:6001
   slots:[0-5460] (5461 slots) master
M: 6a453f24e821a5df4d109629743567eed2771119 127.0.0.1:6002
   slots:[5461-10922] (5462 slots) master
M: 47914d4a346e7952a27620582a49290da175f1ce 127.0.0.1:6003
   slots:[10923-16383] (5461 slots) master
S: 2d2ba0af58337f6793a796c28574311639ef2540 127.0.0.1:6004
   replicates 47914d4a346e7952a27620582a49290da175f1ce
S: ccd8df5edc7be654f47a49c2a2cd28206c2de0eb 127.0.0.1:6005
   replicates 8bf8e2e6d2c180acbc06dc9554a56f2a4755f004
S: 4255bb35df2e7d2332262e2cde95612eb5193500 127.0.0.1:6006
   replicates 6a453f24e821a5df4d109629743567eed2771119
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
....
>>> Performing Cluster Check (using node 127.0.0.1:6001)
M: 8bf8e2e6d2c180acbc06dc9554a56f2a4755f004 127.0.0.1:6001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: ccd8df5edc7be654f47a49c2a2cd28206c2de0eb 127.0.0.1:6005
   slots: (0 slots) slave
   replicates 8bf8e2e6d2c180acbc06dc9554a56f2a4755f004
M: 6a453f24e821a5df4d109629743567eed2771119 127.0.0.1:6002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 2d2ba0af58337f6793a796c28574311639ef2540 127.0.0.1:6004
   slots: (0 slots) slave
   replicates 47914d4a346e7952a27620582a49290da175f1ce
M: 47914d4a346e7952a27620582a49290da175f1ce 127.0.0.1:6003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 4255bb35df2e7d2332262e2cde95612eb5193500 127.0.0.1:6006
   slots: (0 slots) slave
   replicates 6a453f24e821a5df4d109629743567eed2771119
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

image-20240710000243101

测试集群
[root@localhost redis6006]# redis-cli -p 6001  -c
#加-c参数,节点之间就可以互相跳转
127.0.0.1:6001> cluster slots			#查看节点的哈希槽编号范围
1) 1) (integer) 5461
   2) (integer) 10922									#哈希槽编号范围
   3) 1) "127.0.0.1"
      2) (integer) 6003									#主节点IP和端口号
      3) "fdca661922216dd69a63a7c9d3c4540cd6baef44"
   4) 1) "127.0.0.1"
      2) (integer) 6004									#从节点IP和端口号
      3) "a2c0c32aff0f38980accd2b63d6d952812e44740"
2) 1) (integer) 0
   2) (integer) 5460
   3) 1) "127.0.0.1"
      2) (integer) 6001
      3) "0e5873747a2e26bdc935bc76c2bafb19d0a54b11"
   4) 1) "127.0.0.1"
      2) (integer) 6006
      3) "8842ef5584a85005e135fd0ee59e5a0d67b0cf8e"
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "127.0.0.1"
      2) (integer) 6002
      3) "816ddaa3d1469540b2ffbcaaf9aa867646846b30"
   4) 1) "127.0.0.1"
      2) (integer) 6005
      3) "f847077bfe6722466e96178ae8cbb09dc8b4d5eb"
生成数据测试
127.0.0.1:6001> set name zhangsan
# 对name  键进行算法 得出  值 为  5789  跳到对应的节点存储
-> Redirected to slot [5798] located at 127.0.0.1:6002
OK
127.0.0.1:6002> 
查看name键的槽编号
127.0.0.1:6001> cluster keyslot name					#查看name键的槽编号
查看节点信息
cluster nodes
posted @   红荼  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示