redis
Redis简介
说明
Redis (Remote Dictionary Server远程字典服务)是一个遵循BSD MIT开源协议的高性能的NoSQL.Redis 基于ANSI C语言语言)编写的key-value数据库,是意大利的Salvatore Sanfilippo在2009年发布,从2010 年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal公司赞助。 目前国内外使用的公司众多,比如:阿里,腾讯,百度,京东,新浪微博,GitHub,Twitter 等 Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库 起到很好的补充作用。它提供了Java,C/C++,Go, C#,PHP,JavaScript,Perl,Object-C,Python, Ruby,Erlang等客户端
特性
- 速度快: 10W QPS,基于内存,C语言实现
- 单线程
持久化 - 支持多种数据结构
- 支持多种编程语言
- 功能丰富: 支持Lua脚本,发布订阅,事务,pipeline等功能
- 简单: 代码短小精悍(单机核心代码只有23000行左右),单线程开发容易,不依赖外部库,使用简单
- 主从复制
- 支持高可用和分布式
单线程
说明
Redis 6.0版本前一直是单线程方式处理用户的请求
单线程为何如此快?
- 纯内存
- 非阻塞
- 避免线程切换和竞态消耗
主要事项
- 一次只运行一条命令
- 避免执行长(慢)命令:keys *, flushall, flushdb, slow lua script, mutil/exec, operate big
value(collection) - 其实不是单线程: 早期版本是单进程单线程,3.0 版本后实际还有其它的线程, 实现特定功能,如: fysnc
file descriptor,close file descriptor
Redis 对比 Memcached
比较类别 | Redis | Redis memcached |
---|---|---|
支持的数据结构 | 哈希、列表、集合、有序集合 | 纯kev-value |
持久化支持 | 有 | 无 |
高可用支持 | redis支持集群功能,可以实现主动复制,读写分离。官方也提供了sentinel集群管理工具,能够实现主从服务监控,故障自动转移,这一切,对于客户端都是透明的,无需程序改动,也无需人工介入 | 需要二次开发 |
存储value容量 | 最大512M | 最大1M |
内存分配 | 临时申请空间,可能导致碎片 | 预分配内存池的方式管理内存,能够省去内存分配时间 |
虚拟内存使用 | 有自己的VM机制,理论上能够存储比物理内存更多的数据,当数据超量时,会引发swap,把冷数据刷到磁盘上 | 所有的数据存储在物理内存里 |
网络模型 | 非阻塞IO复用模型,提供一些非KV存储之外的排序,聚合功能,在执行这些功能时,复杂的CPU计算,会阻塞整个IO调度 | 非阻塞IO复用模型 |
水平扩展的支持 | redis cluster 可以横向扩展暂 | 无 |
多线程 | Redis6.0之前是只支持单线程 | Memcached支持多线程,CPU利用方面Memcache优于Redis |
过期策略 | 有专门线程,清除缓存数据 | 懒淘汰机制:每次往缓存放入数据的时候,都会存一个时间,在读取的时候要和设置的时间做TTL比较来判断是否过期 |
单机QPS | 约10W | 约60W |
源代码可读性 | 代码清爽简洁 | 可能是考虑了太多的扩展性,多系统的兼容性,代码不清爽 |
适用场景 | 复杂数据结构、有持久化、高可用需求、value存储内容较大 | 纯KV,数据量非常大,并发量非常大的业务 |
Redis 常见应用场景
- 缓存:缓存RDBMS中数据,比如网站的查询结果、商品信息、微博、新闻、消息
- Session 共享:实现Web集群中的多服务器间的session共享
- 计数器:商品访问排行榜、浏览数、粉丝数、关注、点赞、评论等和次数相关的数值统计场景
- 社交:朋友圈、共同好友、可能认识他们等
- 地理位置: 基于地理信息系统GIS(Geographic Information System)实现摇一摇、附近的人、外卖
等功能 - 消息队列:ELK等日志系统缓存、业务的订阅/发布系统
缓存的实现流程
数据更新操作流程:
数据读操作流程:
Redis安装
-
官网下载地址
http://download.redis.io/releases/
yum/dnf安装
-
查看yum可安装的redis信息
#CentOS 8 由系统源提供,在CentOS7系统上需要安装EPEL源 [root@Rocky_100 ~]#yum info redis 上次元数据过期检查:0:10:38 前,执行于 2022年09月27日 星期二 21时45分22秒。 可安装的软件包 名称 : redis 版本 : 5.0.3 发布 : 5.module+el8.5.0+657+2674830e 架构 : x86_64 大小 : 926 k 源 : redis-5.0.3-5.module+el8.5.0+657+2674830e.src.rpm 仓库 : AppStream 概况 : A persistent key-value database URL : http://redis.io 协议 : BSD and MIT 描述 : Redis is an advanced key-value store. It is often referred to as a data : structure server since keys can contain strings, hashes, lists, sets and : sorted sets. -
安装Redis命令
dnf -y install redis -
开机启动Redis
systemctl enable --now redis -
查看redis端口
[root@Rocky_100 ~]#ss -tnl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* -
查看redis进程和线程
[root@Rocky_100 ~]#pstree -p|grep redis |-redis-server(1755)-+-{redis-server}(1756) | |-{redis-server}(1757) | `-{redis-server}(1758) -
进入命令行
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> -
ping命令可用于检测redis实例是否存活,如果存活则显示PONG
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> ping PONG 127.0.0.1:6379> [root@Rocky_100 ~]#redis-cli ping PONG -
info:提供服务器的信息和统计
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> info # Server redis_version:5.0.3 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:7fa21edfc0646001 redis_mode:standalone os:Linux 4.18.0-348.el8.0.2.x86_64 x86_64 arch_bits:64 multiplexing_api:epoll .......
编译安装
-
Redis 源码包官方下载链接:
http://download.redis.io/releases/ -
下载安装
wget http://download.redis.io/releases/redis-6.2.7.tar.gz
编译安装步骤
#安装依赖包 [root@Rocky_100 ~]#yum -y install gcc make jemalloc-devel #如果支持systemd需要安装下面包 [root@Rocky_100 ~]#yum -y install gcc jemalloc-devel systemd-devel #[root@ubuntu2004 ~]#apt -y install make gcc libjemalloc-dev libsystemd-dev #下载源码 [root@Rocky_100 ~]#wget http://download.redis.io/releases/redis-6.2.7.tar.gz [root@Rocky_100 ~]#tar xvf redis-6.2.7.tar.gz #编译安装 [root@Rocky_100 ~]#cd redis-6.2.7/ [root@Rocky_100 redis-6.2.7]#make -j 2 PREFIX=/apps/redis install #指定redis安装目录 #如果支持systemd,需要执行下面 [root@Rocky_100 redis-6.2.7]#make -j 2 USE_SYSTEMD=yes PREFIX=/apps/redis install #配置环境变量 [root@centos8 ~]#echo 'PATH=/apps/redis/bin:$PATH' > /etc/profile.d/redis.sh [root@centos8 ~]#. /etc/profile.d/redis.sh #目录结构 [root@Rocky_100 redis-6.2.7]#tree /apps/redis/ /apps/redis/ └── bin ├── redis-benchmark ├── redis-check-aof -> redis-server ├── redis-check-rdb -> redis-server ├── redis-cli ├── redis-sentinel -> redis-server └── redis-server 1 directory, 6 files [root@Rocky_100 redis-6.2.7]#mkdir /apps/redis/{etc,log,data,run} #创建配置文件、日志、数据等目录 [root@Rocky_100 ~]#cd /root/redis-6.2.7/ [root@Rocky_100 redis-6.2.7]#cp redis.conf /apps/redis/etc/
前台启动 Redis
#redis-server 是 redis 服务器端的主程序 [root@Rocky_100 redis-6.2.7]#redis-server --help Usage: ./redis-server [/path/to/redis.conf] [options] [-] ./redis-server - (read config from stdin) ./redis-server -v or --version ./redis-server -h or --help ./redis-server --test-memory <megabytes> Examples: ./redis-server (run the server with default conf) ./redis-server /etc/redis/6379.conf ./redis-server --port 7777 ./redis-server --port 7777 --replicaof 127.0.0.1 8888 ./redis-server /etc/myredis.conf --loglevel verbose - ./redis-server /etc/myredis.conf --loglevel verbose Sentinel mode: ./redis-server /etc/sentinel.conf --sentinel
前台启动 redis
[root@Rocky_100 redis-6.2.7]#redis-server /apps/redis/etc/redis.conf 12776:C 27 Sep 2022 23:12:41.292 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 12776:C 27 Sep 2022 23:12:41.292 # Redis version=6.2.7, bits=64, commit=00000000, modified=0, pid=12776, just started 12776:C 27 Sep 2022 23:12:41.292 # Configuration loaded 12776:M 27 Sep 2022 23:12:41.293 * monotonic clock: POSIX clock_gettime 12776:M 27 Sep 2022 23:12:41.293 # A key '__redis__compare_helper' was added to Lua globals which is not on the globals allow list nor listed on the deny list. _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.2.7 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 12776 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | https://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 12776:M 27 Sep 2022 23:12:41.294 # Server initialized 12776:M 27 Sep 2022 23:12:41.294 * Ready to accept connections #另外开启命令行终端窗口,查看redis默认服务端口:6379 [root@Rocky_100 redis-6.2.7]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 [::1]:6379 [::]:* LISTEN 0 128 [::]:22 [::]:*
开启 Redis 多实例
[root@Rocky_100 redis-6.2.7]#redis-server --port 6380 12795:C 27 Sep 2022 23:19:37.732 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 12795:C 27 Sep 2022 23:19:37.732 # Redis version=6.2.7, bits=64, commit=00000000, modified=0, pid=12795, just started 12795:C 27 Sep 2022 23:19:37.732 # Configuration loaded 12795:M 27 Sep 2022 23:19:37.734 * monotonic clock: POSIX clock_gettime 12795:M 27 Sep 2022 23:19:37.734 # A key '__redis__compare_helper' was added to Lua globals which is not on the globals allow list nor listed on the deny list. _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.2.7 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6380 | `-._ `._ / _.-' | PID: 12795 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | https://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 12795:M 27 Sep 2022 23:19:37.734 # Server initialized 12795:M 27 Sep 2022 23:19:37.735 * Loading RDB produced by version 6.2.7 12795:M 27 Sep 2022 23:19:37.735 * RDB age 36 seconds 12795:M 27 Sep 2022 23:19:37.735 * RDB memory usage when created 0.77 Mb 12795:M 27 Sep 2022 23:19:37.735 # Done loading RDB, keys loaded: 0, keys expired: 0. 12795:M 27 Sep 2022 23:19:37.735 * DB loaded from disk: 0.000 seconds 12795:M 27 Sep 2022 23:19:37.735 * Ready to accept connections #另外开启命令行终端窗口,查看redis服务端口:6380 [root@Rocky_100 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* LISTEN 0 511 0.0.0.0:6380 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 [::1]:6379 [::]:* LISTEN 0 511 [::]:6380 [::]:* LISTEN 0 128 [::]:22 [::]:* [root@Rocky_100 ~]#ps -ef|grep redis root 12804 1431 0 23:25 pts/0 00:00:00 redis-server 127.0.0.1:6379 root 12811 9247 0 23:26 pts/1 00:00:00 redis-server *:6380 root 12844 12819 0 23:27 pts/2 00:00:00 grep --color=auto redis
消除启动时的三个Warning提示信息(可选)
前面直接启动Redis时有三个Waring信息,可以用下面方法消除告警,但非强制消除
Tcp backlog
WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
-
说明
Tcp backlog 是指TCP的第三次握手服务器端收到客户端 ack确认号之后到服务器用Accept函数处理请求 前的队列长度,即全连接队列 -
配置
#vim /etc/sysctl.conf net.core.somaxconn = 1024 #sysctl -p
overcommit_memory
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
-
内核参数说明:
内核参数overcommit_memory 实现内存分配策略,可选值有三个:0、1、2 0 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则内存 申请失败,并把错误返回给应用进程 1 表示内核允许分配所有的物理内存,而不管当前的内存状态如何 2 表示内核允许分配超过所有物理内存和交换空间总和的内存 -
配置
#vim /etc/sysctl.conf vm.overcommit_memory = 1 #sysctl -p
transparent hugepage
WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled. 警告:您在内核中启用了透明大页面(THP,不同于一般4k内存页,而为2M)支持。 这将在Redis中造成延迟 和内存使用问题。 要解决此问题,请以root 用户身份运行命令“echo never> /sys/kernel/mm/transparent_hugepage/enabled”,并将其添加到您的/etc/rc.local中,以便在 重启后保留设置。禁用THP后,必须重新启动Redis。
-
注意:ubuntu20.04, Rocky8/CentOS8 默认为 never,所以此值无需优化
-
配置
[root@centos8 ~]#echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local [root@Rocky_100 ~]#echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local [root@Rocky_100 ~]#cat /etc/rc.d/rc.local #!/bin/bash # THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES # # It is highly advisable to create own systemd services or udev rules # to run scripts during boot instead of using this file. # # In contrast to previous versions due to parallel execution during boot # this script will NOT be run after all other services. # # Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure # that this script will be executed during boot. touch /var/lock/subsys/local echo never > /sys/kernel/mm/transparent_hugepage/enabled [root@Rocky_100 ~]#chmod +x /etc/rc.d/rc.local [root@Rocky_100 ~]#
验证是否消除 Warning
重新启动redis 服务不再有前面的三个Waring信息
创建 Redis 用户和设置数据目录权限
[root@Rocky_100 ~]#useradd -r -s /sbin/nologin redis [root@Rocky_100 ~]#id redis uid=994(redis) gid=991(redis) 组=991(redis) #设置目录权限 [root@Rocky_100 ~]#chown -R redis.redis /apps/redis/
创建 Redis 服务 Service 文件
#可以复制CentOS8利用yum安装Redis生成的redis.service文件,进行修改 [root@Rocky_100 ~]#scp 10.0.0.8:/lib/systemd/system/redis.service /lib/systemd/system/ [root@Rocky_100 ~]#vim /lib/systemd/system/redis.service [root@Rocky_100 ~]#cat /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 LimitNOFILE=1000000 #指定此值才支持更大的maxclients值 [Install] WantedBy=multi-user.target
Redis 通过Service方式启动
[root@Rocky_100 ~]#systemctl daemon-reload [root@Rocky_100 ~]#systemctl start redis [root@Rocky_100 ~]#systemctl status redis ● redis.service - Redis persistent key-value database Loaded: loaded (/usr/lib/systemd/system/redis.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2022-09-28 00:34:11 CST; 12s ago Main PID: 13010 (redis-server) Tasks: 5 (limit: 12257) Memory: 8.8M CGroup: /system.slice/redis.service └─13010 /apps/redis/bin/redis-server 127.0.0.1:6379 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:C 28 Sep 2022 00:34:11.661 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:C 28 Sep 2022 00:34:11.661 # Redis version=6.2.7, bits=64, commit=00000000, modified=0, pid=130> 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:C 28 Sep 2022 00:34:11.661 # Configuration loaded 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:M 28 Sep 2022 00:34:11.662 * Increased maximum number of open files to 10032 (it was originally> 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:M 28 Sep 2022 00:34:11.662 * monotonic clock: POSIX clock_gettime 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:M 28 Sep 2022 00:34:11.662 # A key '__redis__compare_helper' was added to Lua globals which is > 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:M 28 Sep 2022 00:34:11.663 * Running mode=standalone, port=6379. 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:M 28 Sep 2022 00:34:11.663 # Server initialized 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:M 28 Sep 2022 00:34:11.664 * Ready to accept connections 9月 28 00:34:11 Rocky_100 redis-server[13010]: 13010:M 28 Sep 2022 00:34:11.664 # systemd supervision error: NOTIFY_SOCKET not found! lines 1-19/19 (END) [root@Rocky_100 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 [::1]:6379 [::]:* LISTEN 0 128 [::]:22
验证客户端连接 Redis
-
客户端连接格式
redis-cli -h IP/HOSTNAME -p PORT -a PASSWORD -
连接客户端
#默认无密码 [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> ping PONG 127.0.0.1:6379> INFO # Server redis_version:6.2.7 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:edcdaa437413d981 redis_mode:standalone os:Linux 4.18.0-348.el8.0.2.x86_64 x86_64 arch_bits:64 monotonic_clock:POSIX clock_gettime
自动化脚本一键安装
REDIS_VERSION=redis-6.2.5 #REDIS_VERSION=redis-4.0.14 PASSWORD=123456 INSTALL_DIR=/apps/redis CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'` . /etc/os-release color () { RES_COL=60 MOVE_TO_COL="echo -en \\033[${RES_COL}G" SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_WARNING="echo -en \\033[1;33m" SETCOLOR_NORMAL="echo -en \E[0m" echo -n "$1" && $MOVE_TO_COL echo -n "[" if [ $2 = "success" -o $2 = "0" ] ;then ${SETCOLOR_SUCCESS} echo -n $" OK " elif [ $2 = "failure" -o $2 = "1" ] ;then ${SETCOLOR_FAILURE} echo -n $"FAILED" else ${SETCOLOR_WARNING} echo -n $"WARNING" fi ${SETCOLOR_NORMAL} echo -n "]" echo } prepare(){ if [ $ID = "centos" -o $ID = "rocky" ];then yum -y install gcc make jemalloc-devel systemd-devel else apt update apt -y install gcc make libjemalloc-dev libsystemd-dev fi if [ $? -eq 0 ];then color "安装软件包成功" 0 else color "安装软件包失败,请检查网络配置" 1 exit fi } install() { if [ ! -f ${REDIS_VERSION}.tar.gz ];then wget http://download.redis.io/releases/${REDIS_VERSION}.tar.gz || { color "Redis 源码下载失败" 1 ; exit; } fi tar xf ${REDIS_VERSION}.tar.gz -C /usr/local/src cd /usr/local/src/${REDIS_VERSION} make -j $CUPS USE_SYSTEMD=yes PREFIX=${INSTALL_DIR} install && color "Redis 编译安装完成" 0 || { color "Redis 编译安装失败" 1 ;exit ; } ln -s ${INSTALL_DIR}/bin/redis-* /usr/bin/ mkdir -p ${INSTALL_DIR}/{etc,log,data,run} cp redis.conf ${INSTALL_DIR}/etc/ sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e "/# requirepass/a requirepass $PASSWORD" -e "/^dir .*/c dir ${INSTALL_DIR}/data/" -e "/logfile .*/c logfile ${INSTALL_DIR}/log/redis-6379.log" -e "/^pidfile .*/c pidfile ${INSTALL_DIR}/run/redis_6379.pid" ${INSTALL_DIR}/etc/redis.conf if id redis &> /dev/null ;then color "Redis 用户已存在" 1 else useradd -r -s /sbin/nologin redis color "Redis 用户创建成功" 0 fi chown -R redis.redis ${INSTALL_DIR} cat >> /etc/sysctl.conf <<EOF net.core.somaxconn = 1024 vm.overcommit_memory = 1 EOF sysctl -p if [ $ID = "centos" -o $ID = "rocky" ];then echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local chmod +x /etc/rc.d/rc.local /etc/rc.d/rc.local else echo -e '#!/bin/bash\necho never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local chmod +x /etc/rc.local /etc/rc.local fi cat > /lib/systemd/system/redis.service <<EOF [Unit] Description=Redis persistent key-value database After=network.target [Service] ExecStart=${INSTALL_DIR}/bin/redis-server ${INSTALL_DIR}/etc/redis.conf --supervised systemd ExecStop=/bin/kill -s QUIT \$MAINPID Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 LimitNOFILE=1000000 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now redis &> /dev/null if [ $? -eq 0 ];then color "Redis 服务启动成功,Redis信息如下:" 0 else color "Redis 启动失败" 1 exit fi sleep 2 redis-cli -a $PASSWORD INFO Server 2> /dev/null } prepare install
Redis 的多实例
说明
测试环境中经常使用多实例,需要指定不同实例的相应的端口,配置文件,日志文件等相关配置
配置步骤:以编译安装为例实现 redis 多实例
#生成的文件列表 sed -r '/^ExecStart/s/(.*)redis(.*)$/\1redis6379\2/' [root@Rocky_100 ~]#tree /apps/redis/ /apps/redis/ ├── bin │ ├── redis-benchmark │ ├── redis-check-aof -> redis-server │ ├── redis-check-rdb -> redis-server │ ├── redis-cli │ ├── redis-sentinel -> redis-server │ └── redis-server ├── data ├── etc │ └── redis.conf ├── log └── run 5 directories, 7 files [root@Rocky_100 ~]#mv /apps/redis/etc/{redis.conf,redis6379.conf} [root@Rocky_100 ~]#sed 's/6379/6380/' /apps/redis/etc/redis6379.conf >/apps/redis/etc/redis6380.conf [root@Rocky_100 ~]#sed 's/6379/6381/' /apps/redis/etc/redis6379.conf >/apps/redis/etc/redis6381.conf [root@Rocky_100 ~]#tree /apps/redis/ /apps/redis/ ├── bin │ ├── redis-benchmark │ ├── redis-check-aof -> redis-server │ ├── redis-check-rdb -> redis-server │ ├── redis-cli │ ├── redis-sentinel -> redis-server │ └── redis-server ├── data ├── etc │ ├── redis6379.conf │ ├── redis6380.conf │ └── redis6381.conf ├── log └── run 5 directories, 9 files #可以先从yum安装的redis拷贝systemd启动服务:/usr/lib/systemd/system/redis.service [root@Rocky_100 ~]#cat /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 LimitNOFILE=1000000 #指定此值才支持更大的maxclients值 [Install] WantedBy=multi-user.target [root@Rocky_100 ~]#mv /usr/lib/systemd/system/{redis.service,redis6379.service} [root@Rocky_100 ~]#sed -ri '/^ExecStart/s/(.*)redis(.*)$/\1redis6379\2/' /usr/lib/systemd/system/redis6379.service [root@Rocky_100 ~]#sed -r '/^ExecStart/s/(.*)redis.*(\..*)$/\1redis6380\2/' /usr/lib/systemd/system/redis6379.service > /usr/lib/systemd/system/redis6380.service [root@Rocky_100 ~]#sed -r '/^ExecStart/s/(.*)redis.*(\..*)$/\1redis6381\2/' /usr/lib/systemd/system/redis6379.service > /usr/lib/systemd/system/redis6381.service [root@Rocky_100 ~]#cat /usr/lib/systemd/system/redis6379.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 LimitNOFILE=1000000 #指定此值才支持更大的maxclients值 [Install] WantedBy=multi-user.target [root@Rocky_100 ~]#cat /usr/lib/systemd/system/redis6380.service [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 LimitNOFILE=1000000 #指定此值才支持更大的maxclients值 [Install] WantedBy=multi-user.target [root@Rocky_100 ~]#cat /usr/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/redis6381.conf --supervised systemd ExecStop=/bin/kill -s QUIT $MAINPID Type=notify #如果支持systemd可以启用此行 User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 LimitNOFILE=1000000 #指定此值才支持更大的maxclients值 [Install] WantedBy=multi-user.target [root@Rocky_100 ~]#systemctl enable --now redis6379 Created symlink /etc/systemd/system/multi-user.target.wants/redis6379.service → /usr/lib/systemd/system/redis6379.service. [root@Rocky_100 ~]#systemctl enable --now redis6380 Created symlink /etc/systemd/system/multi-user.target.wants/redis6380.service → /usr/lib/systemd/system/redis6380.service. [root@Rocky_100 ~]#systemctl enable --now redis6381 Created symlink /etc/systemd/system/multi-user.target.wants/redis6381.service → /usr/lib/systemd/system/redis6381.service. [root@Rocky_100 ~]#ss -tnl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* LISTEN 0 511 127.0.0.1:6380 0.0.0.0:* LISTEN 0 511 127.0.0.1:6381 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 [::1]:6379 [::]:* LISTEN 0 511 [::1]:6380 [::]:* LISTEN 0 511 [::1]:6381 [::]:* LISTEN 0 128 [::]:22 [::]:*
Redis 相关工具和客户端连接
安装的相关程序介绍
[root@Rocky_100 ~]#ll /apps/redis/bin/ 总用量 24904 -rwxr-xr-x 1 redis redis 6551232 9月 27 22:57 redis-benchmark #性能测试程序 lrwxrwxrwx 1 redis redis 12 9月 27 22:57 redis-check-aof -> redis-server #AOF文件检查程序 lrwxrwxrwx 1 redis redis 12 9月 27 22:57 redis-check-rdb -> redis-server #RDB文件检查程序 -rwxr-xr-x 1 redis redis 6767608 9月 27 22:57 redis-cli #客户端程序 lrwxrwxrwx 1 redis redis 12 9月 27 22:57 redis-sentinel -> redis-server #哨兵程序,软连接到服务器端主程序 -rwxr-xr-x 1 redis redis 12176976 9月 27 22:57 redis-server #服务端主程序
客户端程序 redis-cli
#默认为本机无密码连接 redis-cli #远程客户端连接,注意:Redis没有用户的概念 redis-cli -h <Redis服务器IP> -p <PORT> -a <PASSWORD>
程序连接 Redis
https://redis.io/clients
shell 脚本访问 Redis
[root@Rocky_100 ~]#vim redis_test.sh 1 #!/bin/bash 2 # 3 #******************************************************************** 4 #Author: zhangxuelong 5 #QQ: 1024320609 6 #Date: 2022-09-28 7 #FileName: redis_test.sh 8 #URL: https://www.cnblogs.com/zxl1024320609/ 9 #Description: For personal learning 10 #Copyright (C): 2022 All rights reserved 11 #******************************************************************** 12 NUM=10 13 PASS=123456 14 for i in `seq $NUM`;do 15 redis-cli -h 127.0.0.1 -a "$PASS" --no-auth-warning set key${i} value${i} 16 echo "key${i} value${i} 写入完成" 17 done 18 echo "$NUM个key写入完成" [root@Rocky_100 ~]#bash redis_test.sh OK key1 value1 写入完成 OK key2 value2 写入完成 OK key3 value3 写入完成 OK key4 value4 写入完成 OK key5 value5 写入完成 OK key6 value6 写入完成 OK key7 value7 写入完成 OK key8 value8 写入完成 OK key9 value9 写入完成 OK key10 value10 写入完成 10个key写入完成
python 程序连接
python 提供了多种开发库,都可以支持连接访问 Redis
https://redis.io/clients
redis-py库的github :
https://github.com/andymccurdy/redis-py
案例
[root@Rocky_100 ~]#yum info python3-redis 上次元数据过期检查:0:36:03 前,执行于 2022年09月28日 星期三 21时27分19秒。 可安装的软件包 名称 : python3-redis 版本 : 3.5.3 发布 : 1.el8 架构 : noarch 大小 : 142 k 源 : python-redis-3.5.3-1.el8.src.rpm 仓库 : epel 概况 : Python 3 interface to the Redis key-value store URL : https://github.com/andymccurdy/redis-py 协议 : MIT 描述 : This is a Python 3 interface to the Redis key-value store. [root@Rocky_100 ~]#yum -y install python3 python3-redis [root@Rocky_100 ~]#vim redis_python_test.py !/usr/bin/python3 import redis pool = redis.ConnectionPool(host="127.0.0.1",port=6379,password="123456",decode_responses=True) c = redis.Redis(connection_pool=pool) for i in range(10): c.set("k%d" % i,"v%d" % i) data=c.get("k%d" % i) print(data)
图形工具
redis-desktop-manager-0.8.8.384.exe
Redis 配置管理
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 del magedu maxclients 10000 #Redis最大连接客户端 maxmemory <bytes> #redis使用的最大内存,单位为bytes字节,0为不限制,建议设为物理内存一半, 8G内存的计算方式8(G)*1024(MB)1024(KB)*1024(Kbyte),需要注意的是缓冲区是不计算在maxmemory 内,生产中如果不设置此项,可能会导致OOM #maxmemory-policy noeviction 此为默认值 # MAXMEMORY POLICY:当达到最大内存时,Redis 将如何选择要删除的内容。您可以从以下行为中选择一 种: # # volatile-lru -> Evict 使用近似 LRU,只有设置了过期时间的键。 # allkeys-lru -> 使用近似 LRU 驱逐任何键。 # volatile-lfu -> 使用近似 LFU 驱逐,只有设置了过期时间的键。 # allkeys-lfu -> 使用近似 LFU 驱逐任何键。 # volatile-random -> 删除设置了过期时间的随机密钥。 # allkeys-random -> 删除一个随机密钥,任何密钥。 # volatile-ttl -> 删除过期时间最近的key(次TTL) # noeviction -> 不要驱逐任何东西,只是在写操作时返回一个错误。 # # LRU 表示最近最少使用 # LFU 表示最不常用 # # LRU、LFU 和 volatile-ttl 都是使用近似随机算法实现的。 # # 注意:使用上述任何一种策略,当没有合适的键用于驱逐时,Redis 将在需要更多内存的写操作时返回错 误。这些通常是创建新密钥、添加数据或修改现有密钥的命令。一些示例是:SET、INCR、HSET、LPUSH、 SUNIONSTORE、SORT(由于 STORE 参数)和 EXEC(如果事务包括任何需要内存的命令)。 #MAXMEMORY POLICY:当达到最大内存时,Redis 将如何选择要删除的内容。可以从下面行为中进行选 择: # volatile-lru -> 在具有过期集的键中使用近似 LRU 驱逐。 # allkeys-lru -> 使用近似 LRU 驱逐任何键。 # volatile-lfu -> 在具有过期集的键中使用近似 LFU 驱逐。 # allkeys-lfu -> 使用近似 LFU 驱逐任何键。 # volatile-random -> 从具有过期设置的密钥中删除一个随机密钥。 # allkeys-random -> 删除一个随机密钥,任何密钥。 # volatile-ttl -> 删除过期时间最近的key(次TTL) # noeviction -> 不要驱逐任何东西,只是在写操作时返回一个错误。 # # LRU 表示最近最少使用 # LFU 表示最不常用 # # LRU、LFU 和 volatile-ttl 均使用近似实现随机算法。 # # 注意:使用上述任何一种策略,Redis 都会在写入时返回错误操作,当没有合适的键用于驱逐时。 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则可以 继续使用,但是会出现查询数据查不到的情况(因为有数据丢失)。生产建议为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以上
config 命令实现动态修改配置
config 命令用于查看当前redis配置、以及不重启redis服务实现动态更改redis配置等
注意:不是所有配置都可以动态修改,且此方式无法持久保存
CONFIG SET parameter value 时间复杂度:O(1) CONFIG SET 命令可以动态地调整 Redis 服务器的配置(configuration)而无须重启。 可以使用它修改配置参数,或者改变 Redis 的持久化(Persistence)方式。 CONFIG SET 可以修改的配置参数可以使用命令 CONFIG GET * 来列出,所有被 CONFIG SET 修改的配 置参数都会立即生效。 CONFIG GET parameter 时间复杂度: O(N),其中 N 为命令返回的配置选项数量。 CONFIG GET 命令用于取得运行中的 Redis 服务器的配置参数(configuration parameters),在 Redis 2.4 版本中, 有部分参数没有办法用 CONFIG GET 访问,但是在最新的 Redis 2.6 版本中,所 有配置参数都已经可以用 CONFIG GET 访问了。 CONFIG GET 接受单个参数 parameter 作为搜索关键字,查找所有匹配的配置参数,其中参数和值以“键- 值对”(key-value pairs)的方式排列。 比如执行 CONFIG GET s* 命令,服务器就会返回所有以 s 开头的配置参数及参数的值:
设置客户端连接密码
[root@Rocky_100 ~]#redis-cli #设置连接密码 127.0.0.1:6379> CONFIG SET requirepass 123456 OK #查看连接密码 127.0.0.1:6379> CONFIG GET requirepass 1) "requirepass" 2) "123456" 127.0.0.1:6379>
获取当前配置
#奇数行为键,偶数行为值 127.0.0.1:6379> CONFIG GET * 1) "rdbchecksum" 2) "yes" 3) "daemonize" 4) "no" 5) "io-threads-do-reads" 6) "no" 7) "lua-replicate-commands" 8) "yes" 9) "always-show-logo" 10) "no" 11) "protected-mode" ...... #查看bind 127.0.0.1:6379> CONFIG GET bind 1) "bind" 2) "0.0.0.0" #Redis5.0有些设置无法修改,Redis6.2.6版本支持修改bind 127.0.0.1:6379> CONFIG SET bind 127.0.0.1 OK
设置Redis使用的最大内存量
127.0.0.1:6379> CONFIG SET maxmemory 1022500864 OK 127.0.0.1:6379> CONFIG get maxmemory 1) "maxmemory" 2) "1022500864"
慢查询
SLOW LOG案例
[root@centos8 ~]#vim /etc/redis.conf slowlog-log-slower-than 1 #指定超过1us即为慢的指令,默认值为10000us slowlog-max-len 1024 #指定只保存最近的1024条慢记录,默认值为128 127.0.0.1:6379> SLOWLOG LEN #查看慢日志的记录条数 (integer) 14 127.0.0.1:6379> SLOWLOG GET [n] #查看慢日志的n条记录 1) 1) (integer) 14 2) (integer) 1544690617 3) (integer) 4 #第3)行表示每条指令的执行时长 4) 1) "slowlog" 127.0.0.1:6379> SLOWLOG GET 3 1) 1) (integer) 7 2) (integer) 1602901545 3) (integer) 26 4) 1) "SLOWLOG" 2) "get" 5) "127.0.0.1:38258" 6) "" 2) 1) (integer) 6 2) (integer) 1602901540 3) (integer) 22 4) 1) "SLOWLOG" 2) "get" 3) "2" 5) "127.0.0.1:38258" 6) "" 3) 1) (integer) 5 2) (integer) 1602901497 3) (integer) 22 4) 1) "SLOWLOG" 2) "GET" 5) "127.0.0.1:38258" 6) "" 127.0.0.1:6379> SLOWLOG RESET #清空慢日志 OK
Redis 持久化
Redis 是基于内存型的NoSQL, 和MySQL是不同的,使用内存进行数据保存
如果想实现数据的持久化,Redis也也可支持将内存数据保存到硬盘文件中
Redis支持两种数据持久化保存方法
- RDB:Redis DataBase
- AOF:AppendOnlyFile
RDB
RDB 工作原理
RDB(Redis DataBase):是基于某个时间点的快照,注意RDB只保留当前最新版本的一个快照 RDB 持久化功能所生成的 RDB 文件是一个经过压缩的二进制文件,通过该文件可以还原生成该 RDB 文 件时数据库的状态。因为 RDB 文件是保存在磁盘中的,所以即便 Redis 服务进程甚至服务器宕机,只要 磁盘中 RDB 文件存在,就能将数据恢复
RDB bgsave 实现快照的具体过程:
首先从redis 主进程先fork生成一个新的子进程,此子进程负责将Redis内存数据保存为一个临时文件tmp- <子进程pid>.rdb,当数据保存完成后,再将此临时文件改名为RDB文件,如果有前一次保存的RDB文件则 会被替换,最后关闭此子进程 由于Redis只保留最后一个版本的RDB文件,如果想实现保存多个版本的数据,需要人为实现
-
bgsave 执行过程会使用子进程进行快照
[root@Rocky_100 ~]#redis-cli bgsave;pstree -p|grep redis;ll /apps/redis/data/ Background saving started |-redis-server(105224)-+-redis-server(105542) | |-{redis-server}(105230) | |-{redis-server}(105231) | |-{redis-server}(105232) | |-{redis-server}(105233) | `-{redis-server}(105315) 总用量 2512 -rw-r--r-- 1 redis redis 792256 9月 30 18:30 appendonly.aof -rw-r--r-- 1 redis redis 790901 10月 1 10:02 dump.rdb -rw-r--r-- 1 redis redis 471040 10月 1 10:03 temp-105542.rdb
RDB 相关配置
#在配置文件中的 save 选项设置多个保存条件,只有任何一个条件满足,服务器都会自动执行 BGSAVE 命 令 save 900 1 #900s内修改了1个key即触发保存RDB save 300 10 #300s内修改了10个key即触发保存RDB save 60 10000 #60s内修改了10000个key即触发保存RDB dbfilename dump.rdb dir ./ #编泽编译安装时默认RDB文件存放在Redis的工作目录,此配置可指定保存的数据目 录 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes
案例
[root@Rocky_100 ~]#grep save /apps/redis/etc/redis.conf # save <seconds> <changes> # Redis will save the DB if both the given number of seconds and the given # save "" # Unless specified otherwise, by default Redis will save the DB: # save 3600 1 # save 300 100 # save 60 10000 [root@Rocky_100 ~]#redis-cli config get save 1) "save" 2) "3600 1 300 100 60 10000" #禁用系统的自动快照 [root@Rocky_100 ~]#redis-cli config set save="" [root@Rocky_100 ~]#vim /apps/redis/etc/redis.conf [root@Rocky_100 ~]#grep save /apps/redis/etc/redis.conf # save <seconds> <changes> # Redis will save the DB if both the given number of seconds and the given save "" # Unless specified otherwise, by default Redis will save the DB: # save 3600 1 # save 300 100 # save 60 10000
实现 RDB 方法
- save: 同步,不推荐使用,使用主进程完成快照,因此会阻赛其它命令执行
- bgsave: 异步后台执行,不影响其它命令的执行,会开启独立的子进程,因此不会阻赛其它命令执行
- 配置文件实现自动保存: 在配置文件中制定规则,自动执行bgsave
RDB 模式的优缺点
RDB 模式优点
- RDB快照只保存某个时间点的数据,恢复的时候直接加载到内存即可,不用做其他处理,这种文件
适合用于做灾备处理.可以通过自定义时间点执行redis指令bgsave或者save保存快照,实现多个版
本的备份
比如: 可以在最近的24小时内,每小时备份一次RDB文件,并且在每个月的每一天,也备份一个
RDB文件。这样的话,即使遇上问题,也可以随时将数据集还原到指定的不同的版本。 - RDB在大数据集时恢复的速度比AOF方式要快
RDB 模式缺点
- 不能实时保存数据,可能会丢失自上一次执行RDB备份到当前的内存数据
如果需要尽量避免在服务器故障时丢失数据,那么RDB并不适合。虽然Redis允许设置不同的保存
点(save point)来控制保存RDB文件的频率,但是,因为RDB文件需要保存整个数据集的状态,
所以它可能并不是一个非常快速的操作。因此一般会超过5分钟以上才保存一次RDB文件。在这种
情况下,一旦发生故障停机,就可能会丢失较长时间的数据。 - 在数据集比较庞大时,fork()子进程可能会非常耗时,造成服务器在一定时间内停止处理客户端请
求,如果数据集非常巨大,并且CPU时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒
或更久。另外子进程完成生成RDB文件的时间也会花更长时间.
范例: 手动备份RDB文件的脚本
[root@Rocky_100 ~]#tree /apps/redis/ /apps/redis/ ├── bin │ ├── redis-benchmark │ ├── redis-check-aof -> redis-server │ ├── redis-check-rdb -> redis-server │ ├── redis-cli │ ├── redis-sentinel -> redis-server │ └── redis-server ├── data │ ├── appendonly.aof │ └── dump.rdb ├── etc │ ├── redis.conf │ └── redis.confr ├── log │ └── redis.log └── run 5 directories, 11 files [root@Rocky_100 ~]#grep -E '^(save|dir|appendonly)' /apps/redis/etc/redis.conf save "" dir /apps/redis/data appendonly yes [root@Rocky_100 ~]#vim redis_backup.sh 1 #!/bin/bash 2 # 3 #******************************************************************** 4 #Author: zhangxuelong 5 #QQ: 1024320609 6 #Date: 2022-10-01 7 #FileName: redis_backup.sh 8 #URL: https://www.cnblogs.com/zxl1024320609/ 9 #Description: For personal learning 10 #Copyright (C): 2022 All rights reserved 11 #******************************************************************** BACKUP=/backup/redis-rdb DIR=//apps/redis/data FILE=dump.rdb PASS=123456 color () { RES_COL=60 MOVE_TO_COL="echo -en \\033[${RES_COL}G" SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_WARNING="echo -en \\033[1;33m" SETCOLOR_NORMAL="echo -en \E[0m" echo -n "$1" && $MOVE_TO_COL echo -n "[" if [ $2 = "success" -o $2 = "0" ] ;then ${SETCOLOR_SUCCESS} echo -n $" OK " elif [ $2 = "failure" -o $2 = "1" ] ;then ${SETCOLOR_FAILURE} echo -n $"FAILED" else ${SETCOLOR_WARNING} echo -n $"WARNING" fi ${SETCOLOR_NORMAL} echo -n "]" echo } redis-cli -h 127.0.0.1 -a $PASS --no-auth-warning bgsave result=`redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress| sed -rn 's/.*:([0-9]+).*/\1/p'` until [ $result -eq 0 ] ;do sleep 1 result=`redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress| sed -rn 's/.*:([0-9]+).*/\1/p'` done DATE=`date +%F_%H-%M-%S` [ -e $BACKUP ] || { mkdir -p $BACKUP ; chown -R redis.redis $BACKUP; } cp $DIR/$FILE $BACKUP/dump_6379-${DATE}.rdb color "Backup redis RDB" 0 [root@Rocky_100 ~]#bash redis_backup.sh Background saving started Backup redis RDB [ OK ] [root@Rocky_100 ~]#ls /backup/redis-rdb/ dump_6379-2022-10-01_10-41-15.rdb
范例: 观察save 和 bgsave的执行过程
[root@Rocky_100 data]#(redis-cli save &) [root@Rocky_100 data]#ll /apps/redis/data/ 总用量 252432 -rw-r--r-- 1 redis redis 792256 9月 30 18:30 appendonly.aof -rw-r--r-- 1 redis redis 790901 10月 1 10:59 dump6379.rdb -rw-r--r-- 1 redis redis 189855682 10月 1 11:11 dump.rdb -rw-r--r-- 1 redis redis 58138631 10月 1 11:12 temp-105956.rdb [root@Rocky_100 data]#OK [root@Rocky_100 data]#(redis-cli save &);echo save is finished ;redis-cli get class save is finished OK "xxx"
范例: 自动保存
[root@Rocky_100 ~]#vim /apps/redis/etc/redis.conf save 60 3 #测试60s内修改3个key,验证是否生成RDB文件
AOF
AOF 即 AppendOnlyFile,AOF 和 RDB 都采有COW机制,AOF可以指定不同的保存策略,默认为每秒钟 执行一次 fsync,按照操作的顺序地将变更命令追加至指定的AOF日志文件尾部 在第一次启用AOF功能时,会做一次完全备份,后续将执行增量性备份,相当于完全数据备份+增量变化 如果同时启用RDB和AOF,进行恢复时,默认AOF文件优先级高于RDB文件,即会使用AOF文件进行恢复 在第一次开启AOF功能时,会自动备份所有数据到AOF文件中,后续只会记录数据的更新指令
注意: AOF 模式默认是关闭的,第一次开启AOF后,并重启服务生效后,会因为AOF的优先级高于RDB,而
AOF默认没有数据文件存在,从而导致所有数据丢失
范例: 错误开启AOF功能,会导致数据丢失
[root@Rocky_100 data]#redis-cli dbsize (integer) 10100001 [root@Rocky_100 data]#grep '^appendonly' /apps/redis/etc/redis.conf appendonly no [root@Rocky_100 data]#sed -i 's/^appendonly no/appendonly yes/' /apps/redis/etc/redis.conf [root@Rocky_100 data]#grep '^appendonly' /apps/redis/etc/redis.conf appendonly yes [root@Rocky_100 data]#vim /apps/redis/etc/redis.conf [root@Rocky_100 data]#systemctl restart redis.service [root@Rocky_100 data]#redis-cli dbsize (integer) 59820
正确启用AOF功能,访止数据丢失
[root@Rocky_100 data]#grep -E '^(dir|appendonly|dbfilename)' /apps/redis/etc/redis.conf dbfilename dump.rdb dir /apps/redis/data appendonly no [root@Rocky_100 data]#ll /apps/redis/data/ 总用量 186184 -rw-r--r-- 1 redis redis 790901 10月 1 10:59 dump6379.rdb -rw-r--r-- 1 redis redis 189855682 10月 1 11:17 dump.rdb [root@Rocky_100 data]#redis-cli 127.0.0.1:6379> DBSIZE (integer) 10100001 127.0.0.1:6379> config get appendonly 1) "appendonly" 2) "no" 127.0.0.1:6379> config set appendonly yes OK 127.0.0.1:6379> [root@Rocky_100 data]#ll /apps/redis/data/ 总用量 448264 -rw-r--r-- 1 redis redis 0 10月 1 11:48 appendonly.aof -rw-r--r-- 1 redis redis 790901 10月 1 10:59 dump6379.rdb -rw-r--r-- 1 redis redis 189855682 10月 1 11:17 dump.rdb -rw-r--r-- 1 redis redis 145862667 10月 1 11:48 temp-rewriteaof-106160.aof [root@Rocky_100 data]#sed -i 's/appendonly no/appendonly yes/' /apps/redis/etc/redis.conf
补录截图
AOF 相关配置
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数据,此为默认值,也生产建议值 dir /path #rewrite相关 no-appendfsync-on-rewrite yes auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes
范例: 动态修改配置自动生成appendonly.aof文件
127.0.0.1:6379> CONFIG set appendonly yes
AOF rewrite 重写
将一些重复的,可以合并的,过期的数据重新写入一个新的AOF文件,从而节约AOF备份占用的硬盘空间,也 能加速恢复过程 可以手动执行bgrewriteaof 触发AOF,第一次开启AOF功能,或定义自动rewrite 策略
AOF rewrite 过程
AOF rewrite 重写相关配置
#同时在执行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重写 BGREWRITEAOF 命令
BGREWRITEAOF 时间复杂度: O(N), N 为要追加到 AOF 文件中的数据数量。 执行一个 AOF文件 重写操作。重写会创建一个当前 AOF 文件的体积优化版本。 即使 BGREWRITEAOF 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 BGREWRITEAOF 成功之 前不会被修改。 重写操作只会在没有其他持久化工作在后台执行时被触发,也就是说: 如果 Redis 的子进程正在执行快照的保存工作,那么 AOF 重写的操作会被预定(scheduled),等到保存 工作完成之后再执行 AOF 重写。在这种情况下, BGREWRITEAOF 的返回值仍然是 OK ,但还会加上一条 额外的信息,说明 BGREWRITEAOF 要等到保存操作完成之后才能执行。在 Redis 2.6 或以上的版本,可 以使用 INFO [section] 命令查看 BGREWRITEAOF 是否被预定。 如果已经有别的 AOF 文件重写在执行,那么 BGREWRITEAOF 返回一个错误,并且这个新的 BGREWRITEAOF 请求也不会被预定到下次执行。 从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。
范例:手动 bgrewriteaof
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> bgrewriteaof Background append only file rewriting started 127.0.0.1:6379> [root@Rocky_100 ~]#pstree -p |grep redis-server;ll /apps/redis/data/ |-redis-server(106594)-+-redis-server(106619) | |-{redis-server}(106600) | |-{redis-server}(106601) | |-{redis-server}(106602) | |-{redis-server}(106603) | `-{redis-server}(106611) 总用量 502600 -rw-r--r-- 1 redis redis 189855682 10月 2 09:31 appendonly.aof -rw-r--r-- 1 redis redis 790901 10月 1 10:59 dump6379.rdb -rw-r--r-- 1 redis redis 189855682 10月 1 11:17 dump.rdb -rw-r--r-- 1 redis redis 69292041 10月 2 09:37 temp-rewriteaof-106619.aof [root@Rocky_100 ~]#pstree -p |grep redis-server;ll /apps/redis/data/ |-redis-server(106594)-+-{redis-server}(106600) | |-{redis-server}(106601) | |-{redis-server}(106602) | |-{redis-server}(106603) | `-{redis-server}(106611) 总用量 371592 -rw-r--r-- 1 redis redis 189855682 10月 2 09:37 appendonly.aof -rw-r--r-- 1 redis redis 790901 10月 1 10:59 dump6379.rdb -rw-r--r-- 1 redis redis 189855682 10月 1 11:17 dump.rdb
AOF 模式优缺点
AOF 模式优点
-
数据安全性相对较高,根据所使用的fsync策略(fsync是同步内存中redis所有已经修改的文件到存
储设备),默认是appendfsync everysec,即每秒执行一次 fsync,在这种配置下,Redis 仍然可以保
持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync会在后台线程执行,
所以主线程可以继续努力地处理命令请求) -
由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中不需要seek, 即使出现
宕机现象,也不会破坏日志文件中已经存在的内容。然而如果本次操作只是写入了一半数据就出现
了系统崩溃问题,不用担心,在Redis下一次启动之前,可以通过 redis-check-aof 工具来解决数据
一致性的问题 -
Redis可以在 AOF文件体积变得过大时,自动地在后台对AOF进行重写,重写后的新AOF文件包含了
恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为Redis在创建新 AOF文件
的过程中,append模式不断的将修改数据追加到现有的 AOF文件里面,即使重写过程中发生停
机,现有的 AOF文件也不会丢失。而一旦新AOF文件创建完毕,Redis就会从旧AOF文件切换到新
AOF文件,并开始对新AOF文件进行追加操作。 -
AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,也可以通过该文
件完成数据的重建AOF文件有序地保存了对数据库执行的所有写入操作,这些写入操作以Redis协议的格式保存,因
此 AOF文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松。导出(export)AOF文件
也非常简单:举个例子,如果不小心执行了FLUSHALL.命令,但只要AOF文件未被重写,那么只要停
止服务器,移除 AOF文件末尾的FLUSHAL命令,并重启Redis ,就可以将数据集恢复到FLUSHALL执
行之前的状态。
AOF 模式缺点
- 即使有些操作是重复的也会全部记录,AOF 的文件大小一般要大于 RDB 格式的文件
- AOF 在恢复大数据集时的速度比 RDB 的恢复速度要慢
- 如果 fsync 策略是appendfsync no, AOF保存到磁盘的速度甚至会可能会慢于RDB
- bug 出现的可能性更多
RDB和AOF 的选择
如果主要充当缓存功能,或者可以承受较长时间,比如数分钟数据的丢失, 通常生产环境一般只需启用RDB 即可,此也是默认值 如果一点数据都不能丢失,可以选择同时开启RDB和AOF 一般不建议只开启AOF
Redis 常用命令
-
官方文档
https://redis.io/commands -
参考链接:
http://redisdoc.com/ http://doc.redisfans.com/ https://www.php.cn/manual/view/36359.html
INFO:显示当前节点redis运行状态信息
127.0.0.1:6379> INFO # Server redis_version:6.2.7 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:a3a00344fdc6c1f2 redis_mode:standalone os:Linux 4.18.0-348.el8.0.2.x86_64 x86_64 arch_bits:64 monotonic_clock:POSIX clock_gettime multiplexing_api:epoll atomicvar_api:c11-builtin gcc_version:8.5.0 process_id:106594 process_supervised:no run_id:d361cab10690d3916e90125ea2460ab5c5ff20bb tcp_port:6379 server_time_usec:1664675896094508 uptime_in_seconds:1686 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:3731512 executable:/apps/redis/bin/redis-server config_file:/apps/redis/etc/redis.conf io_threads_active:0 # Clients connected_clients:1 cluster_connections:0 maxclients:10000 client_recent_max_input_buffer:32 client_recent_max_output_buffer:0 blocked_clients:0 tracking_clients:0 clients_in_timeout_table:0 # Memory used_memory:861477944 used_memory_human:821.57M used_memory_rss:890003456 used_memory_rss_human:848.77M used_memory_peak:861535256 used_memory_peak_human:821.62M used_memory_peak_perc:99.99% used_memory_overhead:539050176 used_memory_startup:811856 used_memory_dataset:322427768 used_memory_dataset_perc:37.46% allocator_allocated:861592288 allocator_active:861863936 allocator_resident:884035584 total_system_memory:2045001728 total_system_memory_human:1.90G used_memory_lua:32768 used_memory_lua_human:32.00K used_memory_scripts:0 used_memory_scripts_human:0B number_of_cached_scripts:0 maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction allocator_frag_ratio:1.00 allocator_frag_bytes:271648 allocator_rss_ratio:1.03 allocator_rss_bytes:22171648 rss_overhead_ratio:1.01 rss_overhead_bytes:5967872 mem_fragmentation_ratio:1.03 mem_fragmentation_bytes:28568264 mem_not_counted_for_evict:4 mem_replication_backlog:0 mem_clients_slaves:0 mem_clients_normal:20512 mem_aof_buffer:8 mem_allocator:jemalloc-5.1.0 active_defrag_running:0 lazyfree_pending_objects:0 lazyfreed_objects:0 # Persistence loading:0 current_cow_size:0 current_cow_size_age:0 current_fork_perc:0.00 current_save_keys_processed:0 current_save_keys_total:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1664674210 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:-1 rdb_current_bgsave_time_sec:-1 rdb_last_cow_size:0 aof_enabled:1 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:9 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok aof_last_cow_size:442368 module_fork_in_progress:0 module_fork_last_cow_size:0 aof_current_size:189855682 aof_base_size:189855682 aof_pending_rewrite:0 aof_buffer_length:0 aof_rewrite_buffer_length:0 aof_pending_bio_fsync:0 aof_delayed_fsync:0 # Stats total_connections_received:2 total_commands_processed:6 instantaneous_ops_per_sec:0 total_net_input_bytes:222 total_net_output_bytes:20429 instantaneous_input_kbps:0.00 instantaneous_output_kbps:0.00 rejected_connections:0 sync_full:0 sync_partial_ok:0 sync_partial_err:0 expired_keys:0 expired_stale_perc:0.00 expired_time_cap_reached_count:0 expire_cycle_cpu_milliseconds:30 evicted_keys:0 keyspace_hits:0 keyspace_misses:0 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:9445 total_forks:2 migrate_cached_sockets:0 slave_expires_tracked_keys:0 active_defrag_hits:0 active_defrag_misses:0 active_defrag_key_hits:0 active_defrag_key_misses:0 tracking_total_keys:0 tracking_total_items:0 tracking_total_prefixes:0 unexpected_error_replies:0 total_error_replies:2 dump_payload_sanitizations:0 total_reads_processed:9 total_writes_processed:7 io_threaded_reads_processed:0 io_threaded_writes_processed:0 # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:65ec1d3162c2bfe3177f2a323e2fb8129ce53db3 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 # CPU used_cpu_sys:5.526070 used_cpu_user:9.303117 used_cpu_sys_children:2.214705 used_cpu_user_children:14.517913 used_cpu_sys_main_thread:5.499257 used_cpu_user_main_thread:9.311649 # Modules # Errorstats errorstat_ERR:count=1 errorstat_LOADING:count=1 # Cluster cluster_enabled:0 # Keyspace db0:keys=10100001,expires=0,avg_ttl=0 127.0.0.1:6379> info server # Server redis_version:6.2.7 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:a3a00344fdc6c1f2 redis_mode:standalone os:Linux 4.18.0-348.el8.0.2.x86_64 x86_64 arch_bits:64 monotonic_clock:POSIX clock_gettime multiplexing_api:epoll atomicvar_api:c11-builtin gcc_version:8.5.0 process_id:106594 process_supervised:no run_id:d361cab10690d3916e90125ea2460ab5c5ff20bb tcp_port:6379 server_time_usec:1664675945456030 uptime_in_seconds:1735 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:3731561 executable:/apps/redis/bin/redis-server config_file:/apps/redis/etc/redis.conf io_threads_active:0
SELECT:切换数据库
相当于在MySQL的 USE DBNAME 指令
#默认数据库有16个,可通过修改配置文件修改数据库个数:databases 16,同时Cluster模式下不支持多个数据库 127.0.0.1:6379[15]> SELECT 0 OK 127.0.0.1:6379> INFO cluster # Cluster cluster_enabled:0 127.0.0.1:6379> 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
注意: 在Redis cluster 模式下不支持多个数据库,会出现下面错误
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
查看当前库下的所有key,此命令慎用!
127.0.0.1:6379> KEYS * 1) "9527" 2) "9526" 3) "course" 4) "list1" 127.0.0.1:6379> SELECT 1 OK 127.0.0.1:6379[1]> KEYS * (empty list or set) 127.0.0.1:6379[1]> redis>MSET one 1 two 2 three 3 four 4 # 一次设置 4 个 key OK redis> KEYS *o* 1) "four" 2) "two" 3) "one" redis> KEYS t?? 1) "two" redis> KEYS t[w]* 1) "two" redis> KEYS * # 匹配数据库内所有 key 1) "four" 2) "three" 3) "two" 4) "one"
BGSAVE
手动在后台执行RDB持久化操作
127.0.0.1:6379> BGSAVE Background saving started [root@Rocky_100 ~]#redis-cli -h 192.168.100.62 bgsave Background saving started [root@Rocky_100 ~]#ll /apps/redis/data/ 总用量 437064 -rw-r--r-- 1 redis redis 189855682 10月 2 09:37 appendonly.aof -rw-r--r-- 1 redis redis 790901 10月 1 10:59 dump6379.rdb -rw-r--r-- 1 redis redis 189855682 10月 2 10:32 dump.rdb -rw-r--r-- 1 redis redis 39854086 10月 2 10:32 temp-106720.rdb
DBSIZE
返回当前库下的所有key 数量
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> DBSIZE (integer) 10100001 127.0.0.1:6379> SELECT 15 OK 127.0.0.1:6379[15]> DBSIZE (integer) 0
FLUSHDB
强制清空当前库中的所有key,此命令慎用!
##内存当前数据库key都被删除,但磁盘数据未删除,重启redis服务后内存key数据重新加载 [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> SELECT 0 OK 127.0.0.1:6379> DBSIZE (integer) 10100001 127.0.0.1:6379> SELECT 15 OK 127.0.0.1:6379[15]> DBSIZE (integer) 0 127.0.0.1:6379[15]> FLUSHDB OK 127.0.0.1:6379[15]> SELECT 0 OK 127.0.0.1:6379> DBSIZE (integer) 10100001 127.0.0.1:6379> FLUSHDB OK (8.61s) 127.0.0.1:6379> DBSIZE (integer) 0 127.0.0.1:6379> [root@Rocky_100 ~]#ll /apps/redis/data/ 总用量 371592 -rw-r--r-- 1 redis redis 189855724 10月 2 10:36 appendonly.aof -rw-r--r-- 1 redis redis 790901 10月 1 10:59 dump6379.rdb -rw-r--r-- 1 redis redis 189855682 10月 2 10:32 dump.rdb [root@Rocky_100 ~]#systemctl restart redis.service [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> DBSIZE (integer) 10100001 127.0.0.1:6379>
FLUSHALL
强制清空当前Redis服务器所有数据库中的所有key,即删除所有数据,此命令慎用!
#内存所有数据库key都被删除,但磁盘数据未删除,重启redis服务后内存key数据重新加载 [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> DBSIZE (integer) 10100001 127.0.0.1:6379> SELECT 15 OK 127.0.0.1:6379[15]> DBSIZE (integer) 0 127.0.0.1:6379[15]> FLUSHALL OK (8.93s) 127.0.0.1:6379[15]> DBSIZE (integer) 0 127.0.0.1:6379[15]> SELECT 0 OK 127.0.0.1:6379> DBSIZE (integer) 0 127.0.0.1:6379> DBSIZE (integer) 0 127.0.0.1:6379> [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> DBSIZE (integer) 0 127.0.0.1:6379> [root@Rocky_100 ~]#ll /apps/redis/data/ 总用量 371592 -rw-r--r-- 1 redis redis 189855724 10月 2 10:36 appendonly.aof -rw-r--r-- 1 redis redis 790901 10月 1 10:59 dump6379.rdb -rw-r--r-- 1 redis redis 189855682 10月 2 10:32 dump.rdb [root@Rocky_100 ~]#systemctl restart redis.service [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> DBSIZE (error) LOADING Redis is loading the dataset in memory 127.0.0.1:6379> DBSIZE (integer) 10100001 #生产建议修改配置使用rename-command禁用此命令 vim /etc/redis.conf rename-command FLUSHALL "" #rename-command 可能会在后续版本淘汰
SHUTDOWN
可用版本: >= 1.0.0 时间复杂度: O(N),其中 N 为关机时需要保存的数据库键数量。 SHUTDOWN 命令执行以下操作: 关闭Redis服务,停止所有客户端连接 如果有至少一个保存点在等待,执行 SAVE 命令 如果 AOF 选项被打开,更新 AOF 文件 关闭 redis 服务器(server) 如果持久化被打开的话, SHUTDOWN 命令会保证服务器正常关闭而不丢失任何数据。 另一方面,假如只是单纯地执行 SAVE 命令,然后再执行 QUIT 命令,则没有这一保证 —— 因为在执行 SAVE 之后、执行 QUIT 之前的这段时间中间,其他客户端可能正在和服务器进行通讯,这时如果执行 QUIT 就会造成数据丢失。
Redis 数据类型
参考资料:
http://www.redis.cn/topics/data-types.html
相关命令参考:
http://redisdoc.com/http
字符串 string
字符串是一种最基本的Redis值类型。Redis字符串是二进制安全的,这意味着一个Redis字符串能包含任 意类型的数据,例如: 一张JPEG格式的图片或者一个序列化的Ruby对象。一个字符串类型的值最多能 存储512M字节的内容。Redis 中所有 key 都是字符串类型的。此数据类型最为常用
创建一个key
set 指令可以创建一个key 并赋值, 使用格式
SET key value [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 : 只在键已经存在时, 才对键进行设置操作。
范例:
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> DBSIZE (integer) 10100001 127.0.0.1:6379> SELECT 2 OK ##不论key是否存在.都设置 127.0.0.1:6379[2]> set k1 v1 OK 127.0.0.1:6379[2]> get k1 "v1" 127.0.0.1:6379[2]> TYPE k1 ##判断类型 string #Key大小写敏感 127.0.0.1:6379[2]> set name zhang OK 127.0.0.1:6379[2]> get name "zhang" 127.0.0.1:6379[2]> set NAME long OK 127.0.0.1:6379[2]> get name "zhang" 127.0.0.1:6379[2]> get NAME "long" ##设置自动过期时间3s 127.0.0.1:6379[2]> set time 5 ex 5 OK 127.0.0.1:6379[2]> get time "5" 127.0.0.1:6379[2]> get time "5" 127.0.0.1:6379[2]> get time (nil) ##key不存在,才设置,相当于add 127.0.0.1:6379[2]> set title zhang OK 127.0.0.1:6379[2]> setnx title li (integer) 0 127.0.0.1:6379[2]> get title "zhang" 127.0.0.1:6379[2]> setnx title2 li (integer) 1 127.0.0.1:6379[2]> get title2 "li" #key存在,才设置,相当于update 127.0.0.1:6379[2]> set t1 zhang xx (nil) 127.0.0.1:6379[2]> set title2 zhang xx OK 127.0.0.1:6379[2]> get title2 "zhang" 127.0.0.1:6379[2]>
查看一个key的值
127.0.0.1:6379[2]> get name "zhang" #查询不到key 127.0.0.1:6379[2]> get name2 (nil) #get一次只能查询一个key,不可查询多个key 127.0.0.1:6379[2]> get NAME "long" 127.0.0.1:6379[2]> get name NAME (error) ERR wrong number of arguments for 'get' command 127.0.0.1:6379[2]>
删除key
#del可一次删除多个key 127.0.0.1:6379[2]> get name "zhang" 127.0.0.1:6379[2]> del name (integer) 1 127.0.0.1:6379[2]> get name (nil) 127.0.0.1:6379[2]> get NAME "long" 127.0.0.1:6379[2]> get title "zhang" 127.0.0.1:6379[2]> del NAME title (integer) 2 127.0.0.1:6379[2]>
批量设置多个key
127.0.0.1:6379[2]> MSET key1 v1 key2 v2 key3 v3 OK 127.0.0.1:6379[2]> get key1 "v1" 127.0.0.1:6379[2]> get key2 "v2" 127.0.0.1:6379[2]> get key3 "v3" 127.0.0.1:6379[2]>
批量获取多个key
127.0.0.1:6379[2]> MGET key1 key2 key3 1) "v1" 2) "v2" 3) "v3" 127.0.0.1:6379[2]> keys k* 1) "k1" 2) "key2" 3) "key1" 4) "key3" 127.0.0.1:6379[2]> keys * 1) "k1" 2) "key2" 3) "key1" 4) "title2" 5) "key3"
追加key的数据
127.0.0.1:6379[2]> get k1 "v1" 127.0.0.1:6379[2]> APPEND k1 _add (integer) 6 127.0.0.1:6379[2]> get k1 "v1_add" 127.0.0.1:6379[2]>
设置新值并返回旧值
127.0.0.1:6379[2]> set name zhang OK 127.0.0.1:6379[2]> getset name li "zhang" 127.0.0.1:6379[2]> get name "li" 127.0.0.1:6379[2]>
返回字符串 key 对应值的字节数
127.0.0.1:6379[2]> set name zhang OK 127.0.0.1:6379[2]> STRLEN name (integer) 5 127.0.0.1:6379[2]> APPEND name _add (integer) 9 127.0.0.1:6379[2]> get name "zhang_add" 127.0.0.1:6379[2]> STRLEN name (integer) 9 127.0.0.1:6379[2]> set name 张雪龙 OK 127.0.0.1:6379[2]> get name "\xe5\xbc\xa0\xe9\x9b\xaa\xe9\xbe\x99" 127.0.0.1:6379[2]> STRLEN name (integer) 9 127.0.0.1:6379[2]>
判断 key 是否存在
127.0.0.1:6379[2]> SET name zhang ex 10 OK 127.0.0.1:6379[2]> set age 20 OK 127.0.0.1:6379[2]> EXISTS NAME (integer) 0 127.0.0.1:6379[2]> EXISTS NAME age (integer) 1 127.0.0.1:6379[2]> EXISTS name (integer) 0 127.0.0.1:6379[2]>
获取 key 的过期时长
ttl key #查看key的剩余生存时间,如果key过期后,会自动删除 -1 #返回值表示永不过期,默认创建的key是永不过期,重新对key赋值,也会从有剩余生命周期变成永不过 期 -2 #返回值表示没有此key num #key的剩余有效期
案例:
127.0.0.1:6379[2]> TTL name (integer) -2 127.0.0.1:6379[2]> set name zhang ex 100 OK 127.0.0.1:6379[2]> TTL name (integer) 97 127.0.0.1:6379[2]> TTL name (integer) 92 127.0.0.1:6379[2]> set name li OK 127.0.0.1:6379[2]> TTL name (integer) -1 127.0.0.1:6379[2]> set name zhang ex 200 OK 127.0.0.1:6379[2]> TTL name (integer) 197 127.0.0.1:6379[2]> get name "zhang" 127.0.0.1:6379[2]>
重置key的过期时长
127.0.0.1:6379[2]> set age 20 ex 100 OK 127.0.0.1:6379[2]> get age "20" 127.0.0.1:6379[2]> TTL age (integer) 89 127.0.0.1:6379[2]> EXPIRE age 100 (integer) 1 127.0.0.1:6379[2]> TTL age (integer) 98
取消key的期限
即永不过期
127.0.0.1:6379[2]> TTL age (integer) 25 127.0.0.1:6379[2]> PERSIST age (integer) 1 127.0.0.1:6379[2]> TTL age (integer) -1 127.0.0.1:6379[2]>
数字递增
利用INCR命令簇(INCR, DECR, INCRBY,DECRBY)来把字符串当作原子计数器使用。
127.0.0.1:6379[2]> set num 10 OK 127.0.0.1:6379[2]> INCR num (integer) 11 127.0.0.1:6379[2]> get num "11" 127.0.0.1:6379[2]> INCR num (integer) 12 127.0.0.1:6379[2]> get num "12"
数字递减
127.0.0.1:6379[2]> get num "12" 127.0.0.1:6379[2]> DECR num (integer) 11 127.0.0.1:6379[2]> get num "11" 127.0.0.1:6379[2]> DECR num (integer) 10
数字增加
将key对应的数字加decrement(可以是负数)。如果key不存在,操作之前,key就会被置为0。如果key的
value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型
数字。
127.0.0.1:6379[2]> set mynum 10 OK 127.0.0.1:6379[2]> INCRBY mynum 10 (integer) 20 127.0.0.1:6379[2]> get mynum "20" 127.0.0.1:6379[2]> INCRBY mynum -5 (integer) 15 127.0.0.1:6379[2]> get mynum "15" 127.0.0.1:6379[2]>
数字减少
decrby 可以减小数值(也可以增加)
127.0.0.1:6379[2]> get mynum "15" 127.0.0.1:6379[2]> DECRBY mykey 5 (integer) -5 127.0.0.1:6379[2]> DECRBY mynum 5 (integer) 10 127.0.0.1:6379[2]> DECRBY mynum -10 (integer) 20 127.0.0.1:6379[2]> get mynum "20" 127.0.0.1:6379[2]> DECRBY mynum 30 (integer) -10 127.0.0.1:6379[2]> get mynum "-10"
列表 list
Redis列表就是简单的字符串数组,按照插入顺序排序. 支持双向读写,可以添加一个元素到列表的头部 (左边)或者尾部(右边),一个列表最多可以包含2^32-1=4294967295个元素,每个列表元素有下标 来标识,下标 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。 也可以使用负数下 标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,元素值可以重复,常用于存入日 志等场景,此数据类型比较常用
列表特点
- 有序
- 可重复
- 左右都可以操作
创建列表和数据
LPUSH和RPUSH都可以插入列表
LPUSH key value [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[2]> LPUSH name zhang li liu tian wu #根据顺序逐个写入name,最后的wu会在列表的最左侧。 (integer) 3 127.0.0.1:6379> TYPE name list #从右边添加数据 127.0.0.1:6379[2]> RPUSH course java C# VB python linux go (integer) 6 127.0.0.1:6379[2]> type course list
列表追加新数据
127.0.0.1:6379[2]> TYPE name list 127.0.0.1:6379[2]> LPUSH name wang (integer) 6
获取列表长度(元素个数)
127.0.0.1:6379[2]> TYPE name list 127.0.0.1:6379[2]> LLEN name (integer) 6
获取列表指定位置元素数据
127.0.0.1:6379[2]> LPUSH list1 a b c d e (integer) 5 127.0.0.1:6379[2]> LINDEX list1 0 #获取0编号的元素 "e" 127.0.0.1:6379[2]> LINDEX list1 1 "d" 127.0.0.1:6379[2]> LINDEX list1 2 #获取2编号的元素 "c" 127.0.0.1:6379[2]> LINDEX list1 -1 #获取最后一个的元素 "a" #元素从0开始编号 127.0.0.1:6379[2]> LPUSH list1 a b c d e (integer) 5 127.0.0.1:6379[2]> LRANGE list1 1 2 #指定范围 1) "d" 2) "c" 127.0.0.1:6379[2]> LRANGE list1 0 3 1) "e" 2) "d" 3) "c" 4) "b" 127.0.0.1:6379[2]> LRANGE list1 0 -1 #所有元素 1) "e" 2) "d" 3) "c" 4) "b" 5) "a"
修改列表指定索引值
127.0.0.1:6379[2]> RPUSH listkey a b c d e f (integer) 6 127.0.0.1:6379[2]> LRANGE listkey 0 -1 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" 6) "f" 127.0.0.1:6379[2]> lset listkey 2 python OK 127.0.0.1:6379[2]> LRANGE listkey 0 -1 1) "a" 2) "b" 3) "python" 4) "d" 5) "e" 6) "f" 127.0.0.1:6379[2]>
删除列表数据
127.0.0.1:6379> RPUSH list1 a b c d e f (integer) 6 127.0.0.1:6379> LRANGE list1 0 5 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" 6) "f" 127.0.0.1:6379> LPOP list1 "a" 127.0.0.1:6379> LLEN list1 (integer) 5 127.0.0.1:6379> LRANGE list 0 4 (empty array) 127.0.0.1:6379> LRANGE list1 0 4 1) "b" 2) "c" 3) "d" 4) "e" 5) "f" 127.0.0.1:6379> RPOP list1 "f" 127.0.0.1:6379> LLEN list1 (integer) 4 127.0.0.1:6379> LRANGE list1 0 3 1) "b" 2) "c" 3) "d" 4) "e" #LTRIM 对一个列表进行修剪(trim),让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除 127.0.0.1:6379> LLEN list1 (integer) 4 127.0.0.1:6379> LRANGE list1 0 3 1) "b" 2) "c" 3) "d" 4) "e" 127.0.0.1:6379> LTRIM list1 1 2 #只保留1,2号元素 OK 127.0.0.1:6379> LLEN list1 (integer) 2 127.0.0.1:6379> LRANGE list1 0 1 1) "c" 2) "d" #删除list 127.0.0.1:6379> DEL list1 (integer) 1 127.0.0.1:6379> EXISTS list1 (integer) 0
集合 set
Set 是一个无序的字符串合集,同一个集合中的每个元素是唯一无重复的,支持在两个不同的集合中对
数据进行逻辑处理,常用于取交集,并集,统计等场景,例如: 实现共同的朋友
集合特点
- 无序
- 无重复
- 集合间操作
创建集合
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 v1 v2 v3 v4 (integer) 1 127.0.0.1:6379> DEL set1 (integer) 1 127.0.0.1:6379> SADD set1 v1 (integer) 1 127.0.0.1:6379> SADD set1 v2 v3 v4 (integer) 3 127.0.0.1:6379> SADD set1 v2 (integer) 0 127.0.0.1:6379> TYPE set1 set
获取集合的所有数据
127.0.0.1:6379> SMEMBERS set1 1) "v2" 2) "v4" 3) "v3" 4) "v1"
删除集合中的元素
127.0.0.1:6379> SADD goods mobile laptop car (integer) 3 127.0.0.1:6379> SREM goods laptop (integer) 1 127.0.0.1:6379> SMEMBERS goods 1) "car" 2) "mobile" 127.0.0.1:6379>
集合间操作
取集合的交集
交集:同时属于集合A且属于集合B的元素
可以实现共同的朋友
127.0.0.1:6379> smembers set1 1) "v3" 2) "v1" 3) "v2" 4) "v4" 127.0.0.1:6379> smembers set2 1) "v2" 2) "v4" 127.0.0.1:6379> SINTER set1 set2 1) "v2" 2) "v4"
取集合的并集
并集:属于集合A或者属于集合B的元素
127.0.0.1:6379> sadd set1 v1 v2 v3 (integer) 3 127.0.0.1:6379> sadd set2 v2 v3 v4 (integer) 3 127.0.0.1:6379> SUNION set1 set2 1) "v2" 2) "v4" 3) "v1" 4) "v3"
取集合的差集
差集:属于集合A但不属于集合B的元素
可以实现我的朋友的朋友
127.0.0.1:6379> sadd set1 v1 v2 v3 (integer) 3 127.0.0.1:6379> sadd set2 v2 v3 v4 127.0.0.1:6379> SDIFF set1 set2 1) "v1" 127.0.0.1:6379> SDIFF set2 set1 1) "v4"
有序集合 sorted set
Redis有序集合和Redis集合类似,是不包含相同字符串的合集。它们的差别是,每个有序集合的成员都 关联着一个双精度浮点型的评分,这个评分用于把有序集合中的成员按最低分到最高分排序。有序集合 的成员不能重复,但评分可以重复,一个有序集合中最多的成员数为 2^32 - 1=4294967295个,经常用于 排行榜的场景
有序集合特点
- 有序
- 无重复元素
- 每个元素是由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 3 v3 #分数可重复,元素值不可以重复 (integer) 1 127.0.0.1:6379> ZADD zset1 4 v4 (integer) 1 127.0.0.1:6379> TYPE zset1 zset 127.0.0.1:6379> TYPE zset2 none #一次生成多个数据: 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 course 90 linux 99 go 60 python 50 cloud (integer) 4 127.0.0.1:6379> ZRANGE course 0 -1 #正序排序后显示集合内所有的key,按score从小到大显示 1) "cloud" 2) "python" 3) "linux" 4) "go" 127.0.0.1:6379> ZREVRANGE course 0 -1 #倒序排序后显示集合内所有的key,score从大到小显示 1) "go" 2) "linux" 3) "python" 4) "cloud" 127.0.0.1:6379> ZRANGE course 0 -1 withscores #正序显示指定集合内所有key和得分情况 1) "cloud" 2) "50" 3) "python" 4) "60" 5) "linux" 6) "90" 7) "go" 8) "99" 127.0.0.1:6379> ZrevRANGE course 0 -1 withscores #倒序显示指定集合内所有key和得分情况 1) "go" 2) "99" 3) "linux" 4) "90" 5) "python" 6) "60" 7) "cloud" 8) "50" 127.0.0.1:6379>
查看集合的成员个数
127.0.0.1:6379> zcard course (integer) 4 127.0.0.1:6379> zcard zset1 (integer) 4 127.0.0.1:6379> zcard zset2 (integer) 5
基于索引查找数据
127.0.0.1:6379> ZRANge course 0 2 1) "cloud" 2) "python" 3) "linux" 127.0.0.1:6379> ZRANge course 0 20 #超出范围不报错 1) "cloud" 2) "python" 3) "linux" 4) "go" 127.0.0.1:6379> ZRANge course 1 3 1) "python" 2) "linux" 3) "go"
查询指定数据的排名
127.0.0.1:6379> ZADD course 90 linux 100 go 60 python 50 cloud (integer) 4 127.0.0.1:6379> zrank course python (integer) 1 127.0.0.1:6379> zrank course go (integer) 3
删除元素
127.0.0.1:6379> ZADD course 95 linux 199 go 60 python 50 cloud (integer) 4 127.0.0.1:6379> zrange course 0 -1 1) "cloud" 2) "python" 3) "linux" 4) "go" 127.0.0.1:6379> zrem course python linux (integer) 2 127.0.0.1:6379> zrange course 0 -1 1) "cloud" 2) "go"
哈希 hash
hash 即字典, 用于保存字符串字段field和字符串值value之间的映射,即key/value做为数据部分,hash特 别适合用于存储对象场景. 一个hash最多可以包含2^32-1 个key/value键值对
哈希特点
-
无序
-
k/v 对
-
适用于存放相关的数据
创建 hash
格式:
HSET hash field value 时间复杂度: O(1) 将哈希表 hash 中域 field 的值设置为 value 。 如果给定的哈希表并不存在, 那么一个新的哈希表将被创建并执行 HSET 操作。 如果域 field 已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。
范例:
127.0.0.1:6379> hset hash1 name zhang age 20 gender F (integer) 3 127.0.0.1:6379> type hash1 hash 127.0.0.1:6379> HGETALL hash1 1) "name" 2) "zhang" 3) "age" 4) "20" 5) "gender" 6) "F" 127.0.0.1:6379> hset hash1 depart it (integer) 1 127.0.0.1:6379> HGETALL hash1 1) "name" 2) "zhang" 3) "age" 4) "20" 5) "gender" 6) "F" 7) "depart" 8) "it"
查看hash的指定field的value
127.0.0.1:6379> HGETALL hash1 1) "name" 2) "zhang" 3) "age" 4) "20" 5) "gender" 6) "F" 7) "depart" 8) "it" 127.0.0.1:6379> hget hash1 name "zhang" 127.0.0.1:6379> hmget hash1 name age depart 1) "zhang" 2) "20" 3) "it"
删除hash 的指定的 field/value
127.0.0.1:6379> HGETALL hash1 1) "name" 2) "zhang" 3) "age" 4) "20" 5) "gender" 6) "F" 7) "depart" 8) "it" 127.0.0.1:6379> hdel hash1 depart (integer) 1 127.0.0.1:6379> hdel hash1 depart (integer) 0 127.0.0.1:6379> hdel hash1 age (integer) 1 127.0.0.1:6379> HGETALL hash1 1) "name" 2) "zhang" 3) "gender" 4) "F"
批量设置hash key的多个field和value
127.0.0.1:6379> HMSET hash1 name zhang age 20 city haikou OK 127.0.0.1:6379> HGETALL hash1 1) "name" 2) "zhang" 3) "age" 4) "20" 5) "city" 6) "haikou"
查看hash指定field的value
127.0.0.1:6379> HMSET hash1 name zhang age 20 city haikou OK 127.0.0.1:6379> HMGET hash1 name age 1) "zhang" 2) "20"
查看hash的所有field
127.0.0.1:6379> HMSET hash1 name zhang age 20 city haikou OK 127.0.0.1:6379> HKEYS hash1 1) "name" 2) "age" 3) "city"
查看hash 所有value
127.0.0.1:6379> HMSET hash1 name zhang age 20 city haikou OK 127.0.0.1:6379> HVALS hash1 1) "zhang" 2) "20" 3) "haikou"
查看指定 hash的所有field及value
127.0.0.1:6379> HMSET hash1 name zhang age 20 city haikou OK 127.0.0.1:6379> HGETALL hash1 1) "name" 2) "zhang" 3) "age" 4) "20" 5) "city" 6) "haikou"
删除 hash
127.0.0.1:6379> HGETALL hash1 1) "name" 2) "zhang" 3) "age" 4) "20" 5) "city" 6) "haikou" 127.0.0.1:6379> DEL hash1 (integer) 1 127.0.0.1:6379> HGETALL hash1 (empty array) 127.0.0.1:6379> EXISTS hash1 (integer) 0
消息队列
消息队列: 把要传输的数据放在队列中,从而实现应用之间的数据交换 常用功能: 可以实现多个应用系统之间的解耦,异步,削峰/限流等 常用的消息队列应用: Kafka,RabbitMQ,Redis
消息队列分为两种:
- 生产者/消费者模式: Producer/Consumer
- 发布者/订阅者模式: Publisher/Subscriber
生产者消费者模式
模式说明
生产者消费者模式下,多个消费者同时监听一个频道(redis用队列实现),但是生产者产生的一个消息只 能被最先抢到消息的一个消费者消费一次,队列中的消息由可以多个生产者写入,也可以有不同的消费者 取出进行消费处理.此模式应用广泛
生产者生成消息
通过列表实现
127.0.0.1:6379> LPUSH channel message1 (integer) 1 127.0.0.1:6379> LPUSH channel message2 (integer) 2 127.0.0.1:6379> LPUSH channel message3 (integer) 3 127.0.0.1:6379> LPUSH channel message4 (integer) 4
获取所有消息
127.0.0.1:6379> LRANGE channel 0 -1 1) "message4" 2) "message3" 3) "message2" 4) "message1" 127.0.0.1:6379>
消费者消费消息
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> RPOP channel "message1" 127.0.0.1:6379> RPOP channel "message2" 127.0.0.1:6379> RPOP channel "message3" 127.0.0.1:6379> RPOP channel "message4" 127.0.0.1:6379> RPOP channel (nil)
验证队列消息消费完成
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> LRANGE channel 0 -1 (empty array) #验证队列中的消息全部消费完成
发布者订阅模式
模式说明
在发布者订阅者Publisher/Subscriber模式下,发布者Publisher将消息发布到指定的频道channel,事 先监听此channel的一个或多个订阅者Subscriber都会收到相同的消息。即一个消息可以由多个订阅者 获取到. 对于社交应用中的群聊、群发、群公告等场景适用于此模式
订阅者订阅频道
#订阅者01,订阅channel1频道 [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> SUBSCRIBE channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 #订阅者02,订阅channel1频道 [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> SUBSCRIBE channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1
发布者发布消息
[root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> LRANGE channel 0 -1 (empty array) 127.0.0.1:6379> PUBLISH channel1 nihaoya! (integer) 2 127.0.0.1:6379> PUBLISH channel1 哈哈!
各个订阅者都能收到消息
#订阅者01,订阅channel1频道 [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> SUBSCRIBE channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 1) "message" 2) "channel1" 3) "nihaoya!" 1) "message" 2) "channel1" 3) "\xe5\x93\x88\xe5\x93\x88!" #订阅者02,订阅channel1频道 [root@Rocky_100 ~]#redis-cli 127.0.0.1:6379> SUBSCRIBE channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 1) "message" 2) "channel1" 3) "nihaoya!" 1) "message" 2) "channel1" 3) "\xe5\x93\x88\xe5\x93\x88!"
订阅多个频道
#订阅指定的多个频道 127.0.0.1:6379> SUBSCRIBE channel01 channel02
订阅所有频道
127.0.0.1:6379> PSUBSCRIBE * #支持通配符*
订阅匹配的频道
127.0.0.1:6379> PSUBSCRIBE chann* #匹配订阅多个频道
取消订阅频道
127.0.0.1:6379> unsubscribe channel1 1) "unsubscribe" 2) "channel1" 3) (integer) 0
Redis 集群与高可用
Redis单机服务存在数据和服务的单点问题,而且单机性能也存在着上限,可以利用Redis的集群相关技术来 解决这些问题.
Redis 主从复制
Redis 主从复制架构
主从模式(master/slave),和MySQL的主从模式类似,可以实现Redis数据的跨主机的远程备份。 常见客户端连接主从的架构: 程序APP先连接到高可用性 LB 集群提供的虚拟IP,再由LB调度将用户的请求至后端Redis 服务器来真正提供服务
主从复制特点:
- 一个master可以有多个slave
- 一个slave只能有一个master
- 数据流向是从master到slave单向的
- master 可读可写
- slave 只读
主从复制实现
当master出现故障后,可以会提升一个slave节点变成新的Mster,因此Redis Slave 需要设置和master相同 的连接密码,此外当一个Slave提升为新的master 通过持久化实现数据的恢复
当配置Redis复制功能时,强烈建议打开主服务器的持久化功能。否则的话,由于延迟等问题,部署的主
节点Redis服务应该要避免自动启动。
参考案例: 导致主从服务器数据全部丢失
1.假设节点A为主服务器,并且关闭了持久化。并且节点B和节点C从节点A复制数据 2.节点A崩溃,然后由自动拉起服务重启了节点A.由于节点A的持久化被关闭了,所以重启之后没有任何数据 3.节点B和节点C将从节点A复制数据,但是A的数据是空的,于是就把自身保存的数据副本删除。
在关闭主服务器上的持久化,并同时开启自动拉起进程的情况下,即便使用Sentinel来实现Redis的高可
用性,也是非常危险的。因为主服务器可能拉起得非常快,以至于Sentinel在配置的心跳时间间隔内没
有检测到主服务器已被重启,然后还是会执行上面的数据丢失的流程。无论何时,数据安全都是极其重
要的,所以应该禁止主服务器关闭持久化的同时自动启动。
主从命令配置
启用主从同步
Redis Server 默认为 master节点,如果要配置为从节点,需要指定master服务器的IP,端口及连接密码
在从节点执行REPLICAOF MASTER_IP PORT 指令可以启用主从同步复制功能,早期版本使用 SLAVEOF
指令
127.0.0.1:6379> REPLICAOF MASTER_IP PORT #新版推荐使用 127.0.0.1:6379> SLAVEOF MasterIP Port #旧版使用,将被淘汰 127.0.0.1:6379> CONFIG SET masterauth <masterpass>
master节点配置
#master_192.168.100.62 root@Rocky_64 ~]#redis-cli 127.0.0.1:6379> auth 123456 #登录密码 OK 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:e1fb4002a9c8be5ab3e4b574d7407879889c6e9a master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 127.0.0.1:6379> DBSIZE (integer) 10100008 127.0.0.1:6379> get k1000 "v1000"
save01_192.168.100.63节点配置:
[root@Rocky_63 ~]#redis-cli 127.0.0.1:6379> auth 123456 OK #查看未同master步信息 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:6a335f26fbba6efceabfa31ce7211f440df1344c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 #同步master配置命令 127.0.0.1:6379> REPLICAOF 192.168.100.62 6379 OK 127.0.0.1:6379> DBSIZE (integer) 0 #同步master密码 127.0.0.1:6379> CONFIG set masterauth 123456 OK 127.0.0.1:6379> #查看是否同步成功 [root@Rocky_63 ~]#ll /apps/redis/data/ 总用量 262080 -rw-r--r-- 1 redis redis 189856260 10月 2 23:21 dump.rdb [root@Rocky_63 ~]#redis-cli 127.0.0.1:6379> DBSIZE (error) NOAUTH Authentication required. 127.0.0.1:6379> auth 123456 OK 127.0.0.1:6379> DBSIZE (integer) 10100008 #查看同步master后信息 127.0.0.1:6379> info replication # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:7 master_sync_in_progress:0 slave_read_repl_offset:1204 slave_repl_offset:1204 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:6a335f26fbba6efceabfa31ce7211f440df1344c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1204 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1204 127.0.0.1:6379>
save02_192.168.100.64节点配置:
[root@Rocky_64 ~]#redis-cli 127.0.0.1:6379> auth 123456 OK #查看未同master步信息 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:6a335f26fbba6efceabfa31ce7211f440df1344c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 127.0.0.1:6379> DBSIZE (integer) 0 #同步master配置命令 127.0.0.1:6379> REPLICAOF 192.168.100.62 6379 OK #同步master密码 127.0.0.1:6379> CONFIG SET masterauth 123456 OK 127.0.0.1:6379> #查看是否同步成功 [root@Rocky_64 ~]#ll /apps/redis/data/ 总用量 262080 -rw-r--r-- 1 redis redis 189856261 10月 2 23:24 dump.rdb [root@Rocky_64 ~]#redis-cli 127.0.0.1:6379> AUTH 123456 OK 127.0.0.1:6379> DBSIZE (integer) 10100008 #查看同步master后信息 127.0.0.1:6379> info replication # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:6 master_sync_in_progress:0 slave_read_repl_offset:882 slave_repl_offset:882 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:6a335f26fbba6efceabfa31ce7211f440df1344c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:882 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:295 repl_backlog_histlen:588 127.0.0.1:6379>
查看同步后maser_192.168.100.62节点信息
127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=192.168.100.63,port=6379,state=online,offset=2030,lag=1 slave1:ip=192.168.100.64,port=6379,state=online,offset=2030,lag=1 master_failover_state:no-failover master_replid:6a335f26fbba6efceabfa31ce7211f440df1344c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:2030 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:2030 127.0.0.1:6379>
查看同步后maser_192.168.100.62节点日志信息
删除主从同步
在从节点执行 REPLICAOF NO ONE 指令可以取消主从复制
#取消复制,在slave上执行REPLICAOF NO ONE,会断开和master的连接不再主从复制, 但不会清除slave 上已有的数据 127.0.0.1:6379> REPLICAOF no one OK 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:4838f0a7f11d27d39019556cdc41abed648bb6e7 master_replid2:6a335f26fbba6efceabfa31ce7211f440df1344c master_repl_offset:2380 second_repl_offset:2381 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:295 repl_backlog_histlen:2086 127.0.0.1:6379> DBSIZE (integer) 10100008
验证同步
在 master 上观察日志
[root@Rocky_62 ~]#tail /apps/redis/log/redis.log -f 106808:M 02 Oct 2022 10:46:25.192 # systemd supervision error: NOTIFY_SOCKET not found! 106808:M 02 Oct 2022 23:20:53.357 * Replica 192.168.100.63:6379 asks for synchronization 106808:M 02 Oct 2022 23:20:53.357 * Full resync requested by replica 192.168.100.63:6379 106808:M 02 Oct 2022 23:20:53.357 * Replication backlog created, my new replication IDs are '6a335f26fbba6efceabfa31ce7211f440df1344c' and '0000000000000000000000000000000000000000' 106808:M 02 Oct 2022 23:20:53.357 * Starting BGSAVE for SYNC with target: disk 106808:M 02 Oct 2022 23:20:53.491 * Background saving started by pid 107350 107350:C 02 Oct 2022 23:21:17.601 * DB saved on disk 107350:C 02 Oct 2022 23:21:17.617 * RDB: 0 MB of memory used by copy-on-write 106808:M 02 Oct 2022 23:21:17.727 * Background saving terminated with success 106808:M 02 Oct 2022 23:21:21.320 * Synchronization with replica 192.168.100.63:6379 succeeded 106808:M 02 Oct 2022 23:24:28.634 * Replica 192.168.100.64:6379 asks for synchronization 106808:M 02 Oct 2022 23:24:28.634 * Full resync requested by replica 192.168.100.64:6379 106808:M 02 Oct 2022 23:24:28.634 * Starting BGSAVE for SYNC with target: disk 106808:M 02 Oct 2022 23:24:28.653 * Background saving started by pid 107360 107360:C 02 Oct 2022 23:24:45.765 * DB saved on disk 107360:C 02 Oct 2022 23:24:45.778 * RDB: 0 MB of memory used by copy-on-write 106808:M 02 Oct 2022 23:24:45.873 * Background saving terminated with success 106808:M 02 Oct 2022 23:24:47.410 * Synchronization with replica 192.168.100.64:6379 succeeded
在 slave 节点观察日志
[root@Rocky_63 ~]#tail /apps/redis/log/redis-6379.log 34154:S 02 Oct 2022 23:20:53.359 * Partial resynchronization not possible (no cached master) 34154:S 02 Oct 2022 23:20:53.494 * Full resync from master: 6a335f26fbba6efceabfa31ce7211f440df1344c:0 34154:S 02 Oct 2022 23:21:17.731 * MASTER <-> REPLICA sync: receiving 189856260 bytes from master to disk 34154:S 02 Oct 2022 23:21:21.418 * MASTER <-> REPLICA sync: Flushing old data 34154:S 02 Oct 2022 23:21:21.418 * MASTER <-> REPLICA sync: Loading DB in memory 34154:S 02 Oct 2022 23:21:21.432 * Loading RDB produced by version 6.2.7 34154:S 02 Oct 2022 23:21:21.432 * RDB age 28 seconds 34154:S 02 Oct 2022 23:21:21.432 * RDB memory usage when created 822.59 Mb 34154:S 02 Oct 2022 23:21:46.998 # Done loading RDB, keys loaded: 10100021, keys expired: 0. 34154:S 02 Oct 2022 23:21:46.998 * MASTER <-> REPLICA sync: Finished with success
修改slave节点配置文件
#在slave_192.168.100.63配置 [root@Rocky_63 ~]#grep -nE 'replicaof|masterauth' /apps/redis/etc/redis.conf 460:# Master-Replica replication. Use replicaof to make a Redis instance a copy of 479:# replicaof <masterip> <masterport> 486:# masterauth <master-password> [root@Rocky_63 ~]#sed -i '479a replicaof 192.168.100.62 6379' /apps/redis/etc/redis.conf [root@Rocky_63 ~]#sed -i '486a masterauth 123456' /apps/redis/etc/redis.conf [root@Rocky_63 ~]#grep -nE 'replicaof|masterauth' /apps/redis/etc/redis.conf 460:# Master-Replica replication. Use replicaof to make a Redis instance a copy of 479:# replicaof <masterip> <masterport> 480:replicaof 192.168.100.62 6379 487:masterauth 123456 488:# masterauth <master-password> #在slave_192.168.100.64配置 [root@Rocky_64 ~]#grep -nE 'replicaof|masterauth' /apps/redis/etc/redis.conf 460:# Master-Replica replication. Use replicaof to make a Redis instance a copy of 479:# replicaof <masterip> <masterport> 486:# masterauth <master-password> [root@Rocky_64 ~]#sed -i '479a replicaof 192.168.100.62 6379' /apps/redis/etc/redis.conf [root@Rocky_64 ~]#sed -i '486a masterauth 123456' /apps/redis/etc/redis.conf [root@Rocky_64 ~]#grep -nE 'replicaof|masterauth' /apps/redis/etc/redis.conf 460:# Master-Replica replication. Use replicaof to make a Redis instance a copy of 479:# replicaof <masterip> <masterport> 480:replicaof 192.168.100.62 6379 487:masterauth 123456 488:# masterauth <master-password>
master和slave查看状态
#在master_192.168.100.62上查看状态 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=192.168.100.63,port=6379,state=online,offset=3864,lag=0 slave1:ip=192.168.100.64,port=6379,state=online,offset=3864,lag=0 master_failover_state:no-failover master_replid:6a335f26fbba6efceabfa31ce7211f440df1344c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:3864 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:3864 127.0.0.1:6379> #在slave_192.168.100.63上查看状态 127.0.0.1:6379> info replication # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:2 master_sync_in_progress:0 slave_read_repl_offset:4368 slave_repl_offset:4368 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:6a335f26fbba6efceabfa31ce7211f440df1344c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:4368 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:4368 #在slave_192.168.100.64上查看状态 127.0.0.1:6379> info replication # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_read_repl_offset:4424 slave_repl_offset:4424 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:6a335f26fbba6efceabfa31ce7211f440df1344c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:4424 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:3795 repl_backlog_histlen:630
Slave 日志
[root@Rocky_64 ~]#tail /apps/redis/log/redis-6379.log 10841:S 03 Oct 2022 00:07:10.804 * Full resync from master: 6a335f26fbba6efceabfa31ce7211f440df1344c:3794 10841:S 03 Oct 2022 00:07:10.804 * Discarding previously cached master state. 10841:S 03 Oct 2022 00:07:22.973 * MASTER <-> REPLICA sync: receiving 189856261 bytes from master to disk 10841:S 03 Oct 2022 00:07:24.393 * MASTER <-> REPLICA sync: Flushing old data 10841:S 03 Oct 2022 00:07:36.582 * MASTER <-> REPLICA sync: Loading DB in memory 10841:S 03 Oct 2022 00:07:36.597 * Loading RDB produced by version 6.2.7 10841:S 03 Oct 2022 00:07:36.597 * RDB age 26 seconds 10841:S 03 Oct 2022 00:07:36.597 * RDB memory usage when created 822.61 Mb 10841:S 03 Oct 2022 00:07:50.478 # Done loading RDB, keys loaded: 10100021, keys expired: 0. 10841:S 03 Oct 2022 00:07:50.478 * MASTER <-> REPLICA sync: Finished with success
Master日志
[root@Rocky_62 ~]#tail /apps/redis/log/redis.log -f 106808:M 02 Oct 2022 10:46:25.192 # systemd supervision error: NOTIFY_SOCKET not found! 106808:M 02 Oct 2022 23:20:53.357 * Replica 192.168.100.63:6379 asks for synchronization 106808:M 02 Oct 2022 23:20:53.357 * Full resync requested by replica 192.168.100.63:6379 106808:M 02 Oct 2022 23:20:53.357 * Replication backlog created, my new replication IDs are '6a335f26fbba6efceabfa31ce7211f440df1344c' and '0000000000000000000000000000000000000000' 106808:M 02 Oct 2022 23:20:53.357 * Starting BGSAVE for SYNC with target: disk 106808:M 02 Oct 2022 23:20:53.491 * Background saving started by pid 107350 107350:C 02 Oct 2022 23:21:17.601 * DB saved on disk 107350:C 02 Oct 2022 23:21:17.617 * RDB: 0 MB of memory used by copy-on-write 106808:M 02 Oct 2022 23:21:17.727 * Background saving terminated with success 106808:M 02 Oct 2022 23:21:21.320 * Synchronization with replica 192.168.100.63:6379 succeeded 106808:M 02 Oct 2022 23:24:28.634 * Replica 192.168.100.64:6379 asks for synchronization 106808:M 02 Oct 2022 23:24:28.634 * Full resync requested by replica 192.168.100.64:6379 106808:M 02 Oct 2022 23:24:28.634 * Starting BGSAVE for SYNC with target: disk 106808:M 02 Oct 2022 23:24:28.653 * Background saving started by pid 107360 107360:C 02 Oct 2022 23:24:45.765 * DB saved on disk 107360:C 02 Oct 2022 23:24:45.778 * RDB: 0 MB of memory used by copy-on-write 106808:M 02 Oct 2022 23:24:45.873 * Background saving terminated with success 106808:M 02 Oct 2022 23:24:47.410 * Synchronization with replica 192.168.100.64:6379 succeeded
slave 只读状态
127.0.0.1:6379> set key1 v1 (error) READONLY You can't write against a read only replica.
主从复制故障恢复
主从复制故障恢复过程介绍
slave 节点故障和恢复
当 slave 节点故障时,将Redis Client指向另一个 slave 节点即可,并及时修复故障从节点
master 节点故障和恢复
当 master 节点故障时,需要提升slave为新的master
master故障后,只能手动提升一个slave为新master,不支持自动切换。 之后将其它的slave节点重新指定新的master为master节点 Master的切换会导致master_replid发生变化,slave之前的master_replid就和当前master不一致从而 会引发所有 slave的全量同步。
主从复制故障恢复实现
查看当前master:192.168.100.62节点状态
127.0.0.1:6379> INFO Replication # Replication role:master connected_slaves:2 slave0:ip=192.168.100.64,port=6379,state=online,offset=1568,lag=0 slave1:ip=192.168.100.63,port=6379,state=online,offset=1554,lag=0 master_failover_state:no-failover master_replid:e34b3a39985af1591b36aada4f45e099b819184d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1568 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1568
假设当前master节点192.168.100.62故障,提升slave:192.168.100.63为新的master
#查看当前192.168.100.63节点的状态为slave,master指向192.168.100.62 127.0.0.1:6379> INFO Replication # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:down master_last_io_seconds_ago:-1 master_sync_in_progress:0 slave_read_repl_offset:1806 slave_repl_offset:1806 master_link_down_since_seconds:14 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:e34b3a39985af1591b36aada4f45e099b819184d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1806 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1457 repl_backlog_histlen:350
停止192.168.100.63:slave同步并提升为新的master
#将当前 slave 节点提升为 master 角色 127.0.0.1:6379> REPLICAOF NO ONE OK 127.0.0.1:6379> INFO Replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:ba2c5ba0e8e5515611f3528e871ca0052120fa1c master_replid2:e34b3a39985af1591b36aada4f45e099b819184d master_repl_offset:1806 second_repl_offset:1807 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1457 repl_backlog_histlen:350
测试能否写入数据:
127.0.0.1:6379[1]> set key1 val1
修改所有slave 指向新的master节点
#修改192.168.100.64节点指向新的master节点192.168.100.63 127.0.0.1:6379> INFO replication # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:down master_last_io_seconds_ago:-1 master_sync_in_progress:0 slave_read_repl_offset:1806 slave_repl_offset:1806 master_link_down_since_seconds:240 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:e34b3a39985af1591b36aada4f45e099b819184d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1806 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1806 127.0.0.1:6379> REPLICAOF 192.168.100.63 6379 OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:192.168.100.63 master_port:6379 master_link_status:up master_last_io_seconds_ago:3 master_sync_in_progress:0 slave_read_repl_offset:1862 slave_repl_offset:1862 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:ba2c5ba0e8e5515611f3528e871ca0052120fa1c master_replid2:e34b3a39985af1591b36aada4f45e099b819184d master_repl_offset:1862 second_repl_offset:1807 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1862 #查看日志 [root@Rocky_64 ~]#tail -f /apps/redis/log/redis-6379.log 11640:S 06 Oct 2022 13:03:19.125 # Error condition on socket for SYNC: Connection refused 11640:S 06 Oct 2022 13:03:19.614 * Connecting to MASTER 192.168.100.63:6379 11640:S 06 Oct 2022 13:03:19.614 * MASTER <-> REPLICA sync started 11640:S 06 Oct 2022 13:03:19.615 * REPLICAOF 192.168.100.63:6379 enabled (user request from 'id=6 addr=127.0.0.1:61607 laddr=127.0.0.1:6379 fd=8 name= age=1520 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=50 qbuf-free=40904 argv-mem=27 obl=0 oll=0 omem=0 tot-mem=61491 events=r cmd=replicaof user=default redir=-1') 11640:S 06 Oct 2022 13:03:19.616 * Non blocking connect for SYNC fired the event. 11640:S 06 Oct 2022 13:03:19.621 * Master replied to PING, replication can continue... 11640:S 06 Oct 2022 13:03:19.623 * Trying a partial resynchronization (request e34b3a39985af1591b36aada4f45e099b819184d:1807). 11640:S 06 Oct 2022 13:03:19.624 * Successful partial resynchronization with master. 11640:S 06 Oct 2022 13:03:19.624 # Master replication ID changed to ba2c5ba0e8e5515611f3528e871ca0052120fa1c 11640:S 06 Oct 2022 13:03:19.624 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization.
验证slave192.168.100.64备份新master数据:
127.0.0.1:6379> GET key1 "val1"
在新master:192.168.100.63可看到slave
127.0.0.1:6379> INFO Replication # Replication role:master connected_slaves:1 slave0:ip=192.168.100.64,port=6379,state=online,offset=3556,lag=1 master_failover_state:no-failover master_replid:ba2c5ba0e8e5515611f3528e871ca0052120fa1c master_replid2:e34b3a39985af1591b36aada4f45e099b819184d master_repl_offset:3556 second_repl_offset:1807 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1457 repl_backlog_histlen:2100
实现 Redis 的级联复制
即实现基于Slave节点的Slave

master节点无需修改,slave1节点指向master节点,slave2、slave3节点指向slave1节点
#master节点状态 [root@Rocky_62 ~]#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:master connected_slaves:0 master_failover_state:no-failover master_replid:45549809c45994f1a0ef10bbf095a4de58f07ced master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 #slave1指向master节点 [root@Rocky_63 ~]#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> REPLICAOF 192.168.100.62 6379 OK 127.0.0.1:6379> CONFIG set masterauth 123456 OK 127.0.0.1:6379> INFO Replication # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:9 master_sync_in_progress:0 slave_read_repl_offset:56 slave_repl_offset:56 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:1 slave0:ip=192.168.100.64,port=6379,state=wait_bgsave,offset=0,lag=0 master_failover_state:no-failover master_replid:aa39bf29af182d1bc81dfa1a84168cb1621d7a1d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:56 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:56 #slave2指向slave1节点 [root@Rocky_64 ~]#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> REPLICAOF 192.168.100.63 6379 OK 127.0.0.1:6379> CONFIG set masterauth 123456 OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:192.168.100.63 master_port:6379 master_link_status:up master_last_io_seconds_ago:3 master_sync_in_progress:0 slave_read_repl_offset:546 slave_repl_offset:546 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:aa39bf29af182d1bc81dfa1a84168cb1621d7a1d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:546 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:57 repl_backlog_histlen:490 127.0.0.1:6379> #slave3指向slave1节点 [root@Rocky_65 ~]#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> REPLICAOF 192.168.100.63 6379 OK 127.0.0.1:6379> CONFIG SET masterauth 123456 OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:192.168.100.63 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_read_repl_offset:770 slave_repl_offset:770 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:aa39bf29af182d1bc81dfa1a84168cb1621d7a1d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:770 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:743 repl_backlog_histlen:28 127.0.0.1:6379>
查看master节点状态
127.0.0.1:6379> INFO Replication # Replication role:master connected_slaves:1 slave0:ip=192.168.100.63,port=6379,state=online,offset=896,lag=1 master_failover_state:no-failover master_replid:aa39bf29af182d1bc81dfa1a84168cb1621d7a1d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:896 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:896
查看slave1节点状态
127.0.0.1:6379> INFO Replication # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:6 master_sync_in_progress:0 slave_read_repl_offset:938 slave_repl_offset:938 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:2 slave0:ip=192.168.100.64,port=6379,state=online,offset=938,lag=0 slave1:ip=192.168.100.65,port=6379,state=online,offset=938,lag=1 master_failover_state:no-failover master_replid:aa39bf29af182d1bc81dfa1a84168cb1621d7a1d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:938 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:938 #日志 [root@Rocky_63 ~]#tail -f /apps/redis/log/redis-6379.log 35510:S 06 Oct 2022 14:03:30.990 * Replica 192.168.100.64:6379 asks for synchronization 35510:S 06 Oct 2022 14:03:30.990 * Partial resynchronization request from 192.168.100.64:6379 accepted. Sending 0 bytes of backlog starting from offset 533. 35510:S 06 Oct 2022 14:06:06.177 * Replica 192.168.100.65:6379 asks for synchronization 35510:S 06 Oct 2022 14:06:06.177 * Full resync requested by replica 192.168.100.65:6379 35510:S 06 Oct 2022 14:06:06.177 * Starting BGSAVE for SYNC with target: disk 35510:S 06 Oct 2022 14:06:06.234 * Background saving started by pid 35574 35574:C 06 Oct 2022 14:06:16.256 * DB saved on disk 35574:C 06 Oct 2022 14:06:16.263 * RDB: 0 MB of memory used by copy-on-write 35510:S 06 Oct 2022 14:06:16.313 * Background saving terminated with success 35510:S 06 Oct 2022 14:06:17.271 * Synchronization with replica 192.168.100.65:6379 succeeded
在 master 设置key,观察是否同步
#master 127.0.0.1:6379> set key2 vv2 OK #slave1 127.0.0.1:6379> GET key2 "vv2" #slave2和slave3 127.0.0.1:6379> get key2 "vv2"
主从复制优化
主从复制过程
Redis主从复制分为全量同步和增量同步
Redis 的主从同步是非阻塞的,即同步过程不会影响主服务器的正常访问.
全量复制过程
- 主从节点建立连接,验证身份后,从节点向主节点发送PSYNC(2.8版本之前是SYNC)命令
- 主节点向从节点发送FULLRESYNC命令,包括runID和offset
- 从节点保存主节点信息
- 主节点执行BGSAVE保存RDB文件,同时记录新的记录到buffer中
- 主节点发送RDB文件给从节点
- 主节点将新收到buffer中的记录发送至从节点
- 从节点删除本机的旧数据
- 从节点加载RDB
- 从节点同步主节点的buffer信息
增量复制过程

在主从复制首次完成全量同步之后再次需要同步时,从服务器只要发送当前的offset位置(类似于MySQL的
binlog的位置)给主服务器,然后主服务器根据相应的位置将之后的数据(包括写在缓冲区的积压数据)发
送给从服务器,再次将其保存到从节点内存即可。
即首次全量复制,之后的复制基本增量复制实现
主从同步完整过程
主从同步完整过程如下:
- slave发起连接master,验证通过后,发送PSYNC命令
- master接收到PSYNC命令后,执行BGSAVE命令将全部数据保存至RDB文件中,并将后续发生的写
- 操作记录至buffer中
- master向所有slave发送RDB文件
- master向所有slave发送后续记录在buffer中写操作
- slave收到快照文件后丢弃所有旧数据
- slave加载收到的RDB到内存
- slave 执行来自master接收到的buffer写操作
- 当slave完成全量复制后,后续master只会先发送slave_repl_offset信息
- 以后slave比较自身和master的差异,只会进行增量复制的数据即可

复制缓冲区(环形队列)配置参数:
#master的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式: replbacklog-size = 允许从节点最大中断时长 * 主实例offset每秒写入量,比如:master每秒最大写入 64mb,最大允许60秒,那么就要设置为64mb*60秒=3840MB(3.8G),建议此值是设置的足够大 repl-backlog-size 1mb #如果一段时间后没有slave连接到master,则backlog size的内存将会被释放。如果值为0则表示永远不 释放这部份内存。 repl-backlog-ttl 3600
避免全量复制
- 第一次全量复制不可避免,后续的全量复制可以利用小主节点(内存小),业务低峰时进行全量
- 节点运行ID不匹配:主节点重启会导致RUNID变化,可能会触发全量复制,可以利用故障转移,例如哨
兵或集群,而从节点重启动,不会导致全量复制 - 复制积压缓冲区不足: 当主节点生成的新数据大于缓冲区大小,从节点恢复和主节点连接后,会导致全
量复制.解决方法将repl-backlog-size 调大
避免复制风暴
- 单主节点复制风暴
当主节点重启,多从节点复制
解决方法:更换复制拓扑
- 单机器多实例复制风暴
机器宕机后,大量全量复制
解决方法:主节点分散多机器
主从同步优化配置
Redis在2.8版本之前没有提供增量部分复制的功能,当网络闪断或者slave Redis重启之后会导致主从之
间的全量同步,即从2.8版本开始增加了部分复制的功能。
性能相关配置
repl-diskless-sync no # 是否使用无盘方式进行同步RDB文件,默认为no,no表示不使用无盘,需要将 RDB文件保存到磁盘后再发送给slave,yes表示使用无盘,即RDB文件不需要保存至本地磁盘,而且直接通过 网络发送给slave repl-diskless-sync-delay 5 #无盘时复制的服务器等待的延迟时间 repl-ping-slave-period 10 #slave向master发送ping指令的时间间隔,默认为10s repl-timeout 60 #指定ping连接超时时间,超过此值无法连接,master_link_status显示为down状态, 并记录错误日志 repl-disable-tcp-nodelay no #是否启用TCP_NODELAY #设置成yes,则redis会合并多个小的TCP包成一个大包再发送,此方式可以节省带宽,但会造成同步延迟时 长的增加,导致master与slave数据短期内不一致 #设置成no,则master会立即同步数据 repl-backlog-size 1mb #master的写入数据缓冲区,用于记录自上一次同步后到下一次同步前期间的写 入命令,计算公式:repl-backlog-size = 允许slave最大中断时长 * master节点offset每秒写入 量,如:master每秒最大写入量为32MB,最长允许中断60秒,就要至少设置为32*60=1920MB,建议此值是设 置的足够大,如果此值太小,会造成全量复制 repl-backlog-ttl 3600 #指定多长时间后如果没有slave连接到master,则backlog的内存数据将会过 期。如果值为0表示永远不过期。 slave-priority 100 #slave参与选举新的master的优先级,此整数值越小则优先级越高。当master故 障时将会按照优先级来选择slave端进行选举新的master,如果值设置为0,则表示该slave节点永远不会被 选为master节点。 min-replicas-to-write 1 #指定master的可用slave不能少于个数,如果少于此值,master将无法执 行写操作,默认为0,生产建议设为1, min-slaves-max-lag 20 #指定至少有min-replicas-to-write数量的slave延迟时间都大于此秒数 时,master将不能执行写操作
常见主从复制故障
主从硬件和软件配置不一致
主从节点的maxmemory不一致,主节点内存大于从节点内存,主从复制可能丢失数据
rename-command 命令不一致,如在主节点启用flushdb,从节点禁用此命令,结果在master节点执行
flushdb后,导致slave节点不同步
#在从节点定义rename-command flushall "",但是在主节点没有此配置,则当在主节点执行flushall 时,会在从节点提示下面同步错误 10822:S 16 Oct 2020 20:03:45.291 # == CRITICAL == This replica is sending an error to its master: 'unknown command `flushall`, with args beginning with: ' after processing the command '<unknown>' #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>'
master密码错误
如果slave节点配置的master密码错误,导致验证不通过,自然将无法建立主从同步关系。
[root@centos8 ~]#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 版本之间尤其是大版本间可能会存在兼容性问题,如:Redis 3,4,5,6之间
因此主从复制的所有节点应该使用相同的版本
安全模式下无法远程连接
如果开启了安全模式,并且没有设置bind地址和密码,会导致无法远程连接
[root@Rocky_65 ~]#grep ^bind /apps/redis/etc/redis.conf bind 0.0.0.0 -::1 [root@Rocky_65 ~]#sed -i 's/bind 0.0.0.0 -::1/#bind 0.0.0.0 -::1/' /apps/redis/etc/redis.conf [root@Rocky_65 ~]#grep ^#bind /apps/redis/etc/redis.conf #bind 0.0.0.0 -::1 [root@Rocky_65 ~]#grep requirepass /apps/redis/etc/redis.conf requirepass 123456 [root@Rocky_65 ~]#sed -i 's/requirepass 123456/#requirepass 123456/' /apps/redis/etc/redis.conf [root@Rocky_65 ~]#grep '#requirepass' /apps/redis/etc/redis.conf #requirepass 123456 [root@Rocky_65 ~]#systemctl restart redis.service [root@Rocky_65 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 [::]:6379 [::]:* LISTEN 0 128 [::]:22 [::]:* #远程登录 [root@Rocky_62 ~]#redis-cli -h 192.168.100.65 192.168.100.65:6379> KEYS * Error: Connection reset by peer #本机登录 [root@Rocky_65 ~]#redis-cli 127.0.0.1:6379> DBSIZE (integer) 10100010 127.0.0.1:6379> get key1 "value1"
Redis 哨兵(Sentinel)
Redis 集群介绍
主从架构和MySQL的主从复制一样,无法实现master和slave角色的自动切换,即当master出现故障时,
不能实现自动的将一个slave 节点提升为新的master节点,即主从复制无法实现自动的故障转移功能,如果
想实现转移,则需要手动修改配置,才能将 slave 服务器提升新的master节点.此外只有一个主节点支持写
操作,所以业务量很大时会导致Redis服务性能达到瓶颈
需要解决的主从复制的存在以下弊端:
- master和slave角色的自动切换,且不能影响业务
- 提升Redis服务整体性能,支持更高并发访问
哨兵Sentinel工作原理
哨兵Sentinel从Redis2.6版本开始引用,Redis 2.8版本之后稳定可用。生产环境如果要使用此功能建议
使用Redis的2.8版本以上版本
Sentinel 架构和故障转移
Sentinel 架构
Sentinel 故障转移
1、专门的Sentinel 服务进程是用于监控redis集群中Master工作的状态,当Master主服务器发生故障的时 候,可以实现Master和Slave的角色的自动切换,从而实现系统的高可用性 2、Sentinel是一个分布式系统,即需要在多个节点上各自同时运行一个sentinel进程,Sentienl 进程通过流 言协议(gossip protocols)来接收关于Master是否下线状态,并使用投票协议(Agreement Protocols)来 决定是否执行自动故障转移,并选择合适的Slave作为新的Master 3、每个Sentinel进程会向其它Sentinel、Master、Slave定时发送消息,来确认对方是否存活,如果发现某 个节点在指定配置时间内未得到响应,则会认为此节点已离线,即为主观宕机Subjective Down,简称 为 SDOWN 4、如果哨兵集群中的多数Sentinel进程认为Master存在SDOWN,共同利用 is-master-down-by-addr 命令 互相通知后,则认为客观宕机Objectively Down, 简称 ODOWN 5、接下来利用投票算法,从所有slave节点中,选一台合适的slave将之提升为新Master节点,然后自动修 改其它slave相关配置,指向新的master节点,最终实现故障转移failover 6、Redis Sentinel中的Sentinel节点个数应该为大于等于3且最好为奇数 7、客户端初始化时连接的是Sentinel节点集合,不再是具体的Redis节点,即 Sentinel只是配置中心不是代 理。 8、Redis Sentinel 节点与普通 Redis 没有区别,要实现读写分离依赖于客户端程序 9、Sentinel 机制类似于MySQL中的MHA功能,只解决master和slave角色的自动故障转移问题,但单个 Master 的性能瓶颈问题并没有解决 10、Redis 3.0 之前版本中,生产环境一般使用哨兵模式较多,Redis 3.0后推出Redis cluster功能,可以支持更大 规模的高并发环境
Sentinel中的三个定时任务
- 每10 秒每个sentinel 对master和slave执行info
发现slave节点
确认主从关系 - 每2秒每个sentinel通过master节点的channel交换信息(pub/sub)
通过sentinel__:hello频道交互
交互对节点的“看法”和自身信息
实现哨兵架构
以下案例实现一主两从的基于哨兵的高可用Redis架构
哨兵需要先实现主从复制
哨兵的前提是已经实现了Redis的主从复制
注意: master 的配置文件中masterauth 和slave 都必须相同
所有主从节点的 redis.conf 中关健配置
范例: 准备主从环境配置
#在所有主从节点redis,本实验为编译安装 #安装路径 [root@Rocky_62 ~]#tree /apps/redis/ /apps/redis/ ├── bin │ ├── redis-benchmark │ ├── redis-check-aof -> redis-server │ ├── redis-check-rdb -> redis-server │ ├── redis-cli │ ├── redis-sentinel -> redis-server │ └── redis-server ├── data │ ├── appendonly.aof │ └── dump.rdb ├── etc │ ├── redis.conf │ └── redis.confr ├── log │ └── redis.log └── run 5 directories, 12 files [root@Rocky_62 ~]#grep -E '^(bind|masterauth|requirepass)' /apps/redis/etc/redis.conf bind 0.0.0.0 masterauth 123456 requirepass 123456 #在所有从节点执行 [root@Rocky_63 ~]#grep '^replicaof' /apps/redis/etc/redis.conf replicaof 192.168.100.62 6379 #在所有主从节点执行 [root@Rocky_62 ~]#systemctl enable --now redis
master 服务器状态
[root@Rocky_62 ~]#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:master connected_slaves:2 slave0:ip=192.168.100.63,port=6379,state=online,offset=518,lag=0 slave1:ip=192.168.100.64,port=6379,state=online,offset=518,lag=1 master_failover_state:no-failover master_replid:0c531273398490371b050e6fefdb01abe6a82d12 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:518 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:518
slave1服务器状态
[root@Rocky_63 ~]#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.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:6 master_sync_in_progress:0 slave_read_repl_offset:560 slave_repl_offset:560 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:0c531273398490371b050e6fefdb01abe6a82d12 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:560 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:435 repl_backlog_histlen:126
slave2服务器状态
[root@Rocky_64 ~]#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.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_read_repl_offset:700 slave_repl_offset:700 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:0c531273398490371b050e6fefdb01abe6a82d12 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:700 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:85 repl_backlog_histlen:616
编辑哨兵配置
sentinel配置
Sentinel实际上是一个特殊的redis服务器,有些redis指令支持,但很多指令并不支持.默认监听在
26379/tcp端口.
哨兵服务可以和Redis服务器分开部署在不同主机,但为了节约成本一般会部署在一起
所有redis节点使用相同的以下示例的配置文件
#如果是编译安装,在源码目录有sentinel.conf,复制到安装目录即可, #如:/apps/redis/etc/sentinel.conf cp redis-6.2.7/sentinel.conf /apps/redis/etc/sentinel.conf chown -R redis.redis /apps/redis/etc/sentinel.conf vim //apps/redis/etc/sentinel.conf bind 0.0.0.0 port 26379 daemonize yes pidfile "/apps/redis/pid/sentinel.pid" logfile "/apps/redis/log/sentinel.log" dir "/tmp" #工作目录 sentinel monitor mymaster 192.168.100.62 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 #判断mymaster集群中所有节点的主观下线(SDOWN)的时间,单位:毫秒,建议3000 sentinel parallel-syncs mymaster 1 #发生故障转移后,可以同时向新master同步数据的slave的数量,数字越小总同步时间越长,但可以减轻新 master的负载压力 sentinel failover-timeout mymaster 180000 #所有slaves指向新的master所需的超时时间,单位:毫秒 sentinel deny-scripts-reconfig yes #禁止修改脚本
三个哨兵服务器的配置都如下
#修改前配置 [root@Rocky_62 ~]#grep -vE "^#|^$" /apps/redis/etc/sentinel.conf port 26379 daemonize no pidfile /var/run/redis-sentinel.pid logfile "" dir /tmp sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 30000 acllog-max-len 128 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes SENTINEL resolve-hostnames no SENTINEL announce-hostnames no #修改命令 [root@Rocky_62 ~]#sed -i -e '103a sentinel auth-pass mymaster 123456' -e '14a bind 0.0.0.0' -e '/^daemonize/c daemonize yes' -e '/^pidfile/c pidfile \/apps\/redis\/pid\/sentinel.pid' -e '/^logfile/c logfile \/apps\/redis\/log\/sentinel.log' -e '/^sentinel monitor/c sentinel monitor mymaster 192.168.100.62 6379 2' -e '/^sentinel down-after-milliseconds/c sentinel down-after-milliseconds mymaster 3000' -e 's/' /apps/redis/etc/sentinel.conf #修改后配置 [root@Rocky_62 ~]#grep -Ev '^(#|$)' /apps/redis/etc/sentinel.conf bind 0.0.0.0 port 26379 daemonize yes pidfile /apps/redis/pid/sentinel.pid logfile /apps/redis/log/sentinel.log dir "/tmp" sentinel monitor mymaster 192.168.100.62 6379 2 sentinel auth-pass mymaster 123456 sentinel down-after-milliseconds mymaster 3000 acllog-max-len 128 sentinel deny-scripts-reconfig yes sentinel resolve-hostnames no sentinel announce-hostnames no protected-mode no supervised systemd user default on nopass ~* &* +@all sentinel myid 8c48b290c34a79bf164638ca9c7addb0ab583656 sentinel config-epoch mymaster 0 sentinel leader-epoch mymaster 0 sentinel current-epoch 0 sentinel known-replica mymaster 192.168.100.64 6379 sentinel known-replica mymaster 192.168.100.63 6379 #注意此行自动生成必须唯一,一般不需要修改,如果相同则修改此值需重启redis和sentinel服务 sentinel myid 50547f34ed71fd48c197924969937e738a39975b ..... # Generated by CONFIG REWRITE protected-mode no supervised systemd sentinel leader-epoch mymaster 0 sentinel known-replica mymaster 10.0.0.28 6379 sentinel known-replica mymaster 10.0.0.18 6379 sentinel current-epoch 0 #拷贝配置完的sentinel.conf到所有的哨兵服务器上 [root@Rocky_62 ~]#scp /apps/redis/etc/sentinel.conf 192.168.100.63:/apps/redis/etc/sentinel.conf The authenticity of host '192.168.100.63 (192.168.100.63)' can't be established. ECDSA key fingerprint is SHA256:h6kanNCQX5p4qlKWKoHb79Im34zSpNYEZFKlJ6XZIZc. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.100.63' (ECDSA) to the list of known hosts. root@192.168.100.63's password: sentinel.conf 100% 13KB 2.5MB/s 00:00 [root@Rocky_62 ~]#scp /apps/redis/etc/sentinel.conf 192.168.100.64:/apps/redis/etc/sentinel.conf The authenticity of host '192.168.100.64 (192.168.100.64)' can't be established. ECDSA key fingerprint is SHA256:h6kanNCQX5p4qlKWKoHb79Im34zSpNYEZFKlJ6XZIZc. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.100.64' (ECDSA) to the list of known hosts. root@192.168.100.64's password: sentinel.conf
启动哨兵服务
将所有哨兵服务器都启动起来
#如果是编译安装,可以在所有节点生成新的service文件 [root@Rocky_62 ~]#cat /lib/systemd/system/redis-sentinel.service [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 Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target #包括服务文件到其他哨兵服务器上 [root@Rocky_62 ~]#scp /lib/systemd/system/redis-sentinel.service 192.168.100.63:/lib/systemd/system/redis-sentinel.service root@192.168.100.63's password: redis-sentinel.service 100% 294 148.8KB/s 00:00 [root@Rocky_62 ~]#scp /lib/systemd/system/redis-sentinel.service 192.168.100.64:/lib/systemd/system/redis-sentinel.service root@192.168.100.64's password: redis-sentinel.service #所有哨兵服务器执行重新加载服务 systemctl daemon-reload #设置开启启动,并运行sentinel服务 [root@Rocky_62 ~]#systemctl enable --now redis-sentinel.service Created symlink /etc/systemd/system/multi-user.target.wants/redis-sentinel.service → /usr/lib/systemd/system/redis-sentinel.service. [root@Rocky_63 ~]#systemctl enable --now redis-sentinel.service Created symlink /etc/systemd/system/multi-user.target.wants/redis-sentinel.service → /usr/lib/systemd/system/redis-sentinel.service. [root@Rocky_64 ~]#systemctl enable --now redis-sentinel.service Created symlink /etc/systemd/system/multi-user.target.wants/redis-sentinel.service → /usr/lib/systemd/system/redis-sentinel.service. #确保每个哨兵主机myid不同,如果相同,必须手动修改为不同的值 [root@Rocky_62 ~]#grep myid /apps/redis/etc/sentinel.conf sentinel myid 8c48b290c34a79bf164638ca9c7addb0ab583656 [root@Rocky_63 ~]#grep myid /apps/redis/etc/sentinel.conf sentinel myid 8c48b290c34a79bf164638ca9c7addb0ab583663 [root@Rocky_64 ~]#grep myid /apps/redis/etc/sentinel.conf sentinel myid 8c48b290c34a79bf164638ca9c7addb0ab583664
验证哨兵服务
查看哨兵服务端口状态
[root@Rocky_62 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 0.0.0.0:26379 0.0.0.0:* LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:*
查看哨兵日志
master的哨兵日志
[root@Rocky_62 ~]#tail /apps/redis/log/sentinel.log 2538:X 07 Oct 2022 22:05:46.275 * +slave-reconf-inprog slave 192.168.100.64:6379 192.168.100.64 6379 @ mymaster 192.168.100.63 6379 2538:X 07 Oct 2022 22:05:46.275 * +slave-reconf-done slave 192.168.100.64:6379 192.168.100.64 6379 @ mymaster 192.168.100.63 6379 2538:X 07 Oct 2022 22:05:46.346 # +failover-end master mymaster 192.168.100.63 6379 2538:X 07 Oct 2022 22:05:46.346 # +switch-master mymaster 192.168.100.63 6379 192.168.100.62 6379 2538:X 07 Oct 2022 22:05:46.346 * +slave slave 192.168.100.64:6379 192.168.100.64 6379 @ mymaster 192.168.100.62 6379 2538:X 07 Oct 2022 22:05:46.346 * +slave slave 192.168.100.63:6379 192.168.100.63 6379 @ mymaster 192.168.100.62 6379 2538:X 07 Oct 2022 22:07:11.395 # +tilt #tilt mode entered 2538:X 07 Oct 2022 22:07:41.404 # -tilt #tilt mode exited 2538:X 07 Oct 2022 22:07:55.947 # +sdown slave 192.168.100.63:6379 192.168.100.63 6379 @ mymaster 192.168.100.62 6379 2538:X 07 Oct 2022 22:08:03.716 # -sdown slave 192.168.100.63:6379 192.168.100.63 6379 @ mymaster 192.168.100.62 6379
slave的哨兵日志
[root@Rocky_63 ~]#tail /apps/redis/log/sentinel.log 36639:X 07 Oct 2022 22:05:43.130 # -sdown slave 192.168.100.62:6379 192.168.100.62 6379 @ mymaster 192.168.100.63 6379 36639:X 07 Oct 2022 22:05:43.582 # +config-update-from sentinel 8c48b290c34a79bf164638ca9c7addb0ab583656 192.168.100.62 26379 @ mymaster 192.168.100.63 6379 36639:X 07 Oct 2022 22:05:43.582 # +switch-master mymaster 192.168.100.63 6379 192.168.100.62 6379 36639:X 07 Oct 2022 22:05:43.583 * +slave slave 192.168.100.64:6379 192.168.100.64 6379 @ mymaster 192.168.100.62 6379 36639:X 07 Oct 2022 22:05:43.583 * +slave slave 192.168.100.63:6379 192.168.100.63 6379 @ mymaster 192.168.100.62 6379 36639:X 07 Oct 2022 22:07:11.398 # +tilt #tilt mode entered 36639:X 07 Oct 2022 22:07:41.449 # -tilt #tilt mode exited 36639:X 07 Oct 2022 22:07:41.545 * +convert-to-slave slave 192.168.100.63:6379 192.168.100.63 6379 @ mymaster 192.168.100.62 6379 36639:X 07 Oct 2022 22:07:55.950 # +sdown slave 192.168.100.63:6379 192.168.100.63 6379 @ mymaster 192.168.100.62 6379 36639:X 07 Oct 2022 22:08:03.708 # -sdown slave 192.168.100.63:6379 192.168.100.63 6379 @ mymaster 192.168.100.62 6379
当前sentinel状态
在sentinel状态中尤其是最后一行,涉及到masterIP是多少,有几个slave,有几个sentinels,必须是符
合全部服务器数量
[root@Rocky_62 ~]#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=192.168.100.62:6379,slaves=2,sentinels=3 #2个slave,三个sentinel服务器,如果sentinels值不符合,检查myid可能冲突
停止Master 实现故障转移
停止 Master 节点
[root@Rocky_62 ~]#killall redis-server
查看各节点上哨兵信息:
[root@Rocky_62 ~]#redis-cli -a 123456 -p 26379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. AUTH failed: ERR AUTH <password> called without any password configured for the default user. Are you sure your configuration is correct? 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=192.168.100.63:6379,slaves=2,sentinels=3
故障转移时sentinel的日志信息:
[root@Rocky_62 ~]#tail /apps/redis/log/sentinel.log 2538:X 07 Oct 2022 22:32:04.880 # +sdown master mymaster 192.168.100.62 6379 2538:X 07 Oct 2022 22:32:04.957 # +new-epoch 3 2538:X 07 Oct 2022 22:32:04.960 # +vote-for-leader 8c48b290c34a79bf164638ca9c7addb0ab583663 3 2538:X 07 Oct 2022 22:32:04.982 # +odown master mymaster 192.168.100.62 6379 #quorum 2/2 2538:X 07 Oct 2022 22:32:04.982 # Next failover delay: I will not start a failover before Fri Oct 7 22:38:05 2022 2538:X 07 Oct 2022 22:32:06.108 # +config-update-from sentinel 8c48b290c34a79bf164638ca9c7addb0ab583663 192.168.100.63 26379 @ mymaster 192.168.100.62 6379 2538:X 07 Oct 2022 22:32:06.108 # +switch-master mymaster 192.168.100.62 6379 192.168.100.63 6379 2538:X 07 Oct 2022 22:32:06.109 * +slave slave 192.168.100.64:6379 192.168.100.64 6379 @ mymaster 192.168.100.63 6379 2538:X 07 Oct 2022 22:32:06.109 * +slave slave 192.168.100.62:6379 192.168.100.62 6379 @ mymaster 192.168.100.63 6379 2538:X 07 Oct 2022 22:32:09.156 # +sdown slave 192.168.100.62:6379 192.168.100.62 6379 @ mymaster 192.168.100.63 6379
验证故障转移
故障转移后redis.conf中的replicaof行的master IP会被修改
[root@Rocky_64 ~]#grep ^replicaof /apps/redis/etc/redis.conf replicaof 192.168.100.63 6379
哨兵配置文件的sentinel monitor IP 同样也会被修改
[root@Rocky_63 ~]#grep "^[a-Z]" /apps/redis/etc/sentinel.conf bind 0.0.0.0 port 26379 daemonize yes pidfile "/apps/redis/pid/sentinel.pid" logfile "/apps/redis/log/sentinel.log" dir "/apps/redis/data" sentinel monitor mymaster 192.168.100.63 6379 2 #自动修改此行 sentinel auth-pass mymaster 123456 sentinel down-after-milliseconds mymaster 3000 acllog-max-len 128 sentinel deny-scripts-reconfig yes sentinel resolve-hostnames no sentinel announce-hostnames no protected-mode no supervised systemd user default on nopass sanitize-payload ~* &* +@all sentinel myid 8c48b290c34a79bf164638ca9c7addb0ab583663 sentinel config-epoch mymaster 3 sentinel leader-epoch mymaster 3 sentinel current-epoch 3 sentinel known-replica mymaster 192.168.100.62 6379 sentinel known-replica mymaster 192.168.100.64 6379 sentinel known-sentinel mymaster 192.168.100.64 26379 8c48b290c34a79bf164638ca9c7addb0ab583664 sentinel known-sentinel mymaster 192.168.100.62 26379 8c48b290c34a79bf164638ca9c7addb0ab583656 [root@Rocky_64 ~]#grep "^[a-Z]" /apps/redis/etc/sentinel.conf bind 0.0.0.0 port 26379 daemonize yes pidfile "/apps/redis/pid/sentinel.pid" logfile "/apps/redis/log/sentinel.log" dir "/apps/redis/data" sentinel monitor mymaster 192.168.100.63 6379 2 #自动修改此行 sentinel auth-pass mymaster 123456 sentinel down-after-milliseconds mymaster 3000 acllog-max-len 128 sentinel deny-scripts-reconfig yes sentinel resolve-hostnames no sentinel announce-hostnames no protected-mode no supervised systemd user default on nopass sanitize-payload ~* &* +@all sentinel myid 8c48b290c34a79bf164638ca9c7addb0ab583664 sentinel config-epoch mymaster 3 sentinel leader-epoch mymaster 3 sentinel current-epoch 3 sentinel known-replica mymaster 192.168.100.62 6379 sentinel known-replica mymaster 192.168.100.64 6379 sentinel known-sentinel mymaster 192.168.100.63 26379 8c48b290c34a79bf164638ca9c7addb0ab583663 sentinel known-sentinel mymaster 192.168.100.62 26379 8c48b290c34a79bf164638ca9c7addb0ab583656
验证 Redis 各节点状态
新的master 状态
[root@Rocky_63 ~]#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:master #提升为master connected_slaves:1 slave0:ip=192.168.100.64,port=6379,state=online,offset=6914589,lag=0 master_failover_state:no-failover master_replid:b146c39423d21f68020482aa42d03add97aa9e5b master_replid2:b20927c6a5de8785ea45619f02c386515e043d6b master_repl_offset:6914732 second_repl_offset:6641532 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:6332786 repl_backlog_histlen:581947
另一个slave指向新的master
[root@Rocky_64 ~]#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.100.63 master_port:6379 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_read_repl_offset:6929259 slave_repl_offset:6929259 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:b146c39423d21f68020482aa42d03add97aa9e5b master_replid2:b20927c6a5de8785ea45619f02c386515e043d6b master_repl_offset:6929259 second_repl_offset:6641532 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:5880684 repl_backlog_histlen:1048576
原master重新加入Redis集群
[root@Rocky_62 ~]#grep ^replicaof /apps/redis/etc/redis.conf [root@Rocky_62 ~]#systemctl start redis [root@Rocky_62 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* LISTEN 0 511 0.0.0.0:26379 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* [root@Rocky_62 ~]#grep ^replicaof /apps/redis/etc/redis.conf replicaof 192.168.100.63 6379 #sentinel会自动修改下面行指向新的master
在原 master上观察状态
[root@Rocky_62 ~]#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.100.63 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_read_repl_offset:6993051 slave_repl_offset:6993051 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:b146c39423d21f68020482aa42d03add97aa9e5b master_replid2:0000000000000000000000000000000000000000 master_repl_offset:6993051 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:6969280 repl_backlog_histlen:23772 [root@Rocky_62 ~]#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=192.168.100.63:6379,slaves=2,sentinels=3
观察新master上状态和日志
127.0.0.1:6379> [root@Rocky_63 ~]#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:master connected_slaves:2 slave0:ip=192.168.100.64,port=6379,state=online,offset=7023420,lag=0 slave1:ip=192.168.100.62,port=6379,state=online,offset=7023420,lag=0 master_failover_state:no-failover master_replid:b146c39423d21f68020482aa42d03add97aa9e5b master_replid2:b20927c6a5de8785ea45619f02c386515e043d6b master_repl_offset:7023563 second_repl_offset:6641532 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:6332786 repl_backlog_histlen:690778 [root@Rocky_63 ~]#tail -f /apps/redis/log/sentinel.log 36639:X 07 Oct 2022 22:32:06.776 * +slave-reconf-inprog slave 192.168.100.64:6379 192.168.100.64 6379 @ mymaster 192.168.100.62 6379 36639:X 07 Oct 2022 22:32:06.776 * +slave-reconf-done slave 192.168.100.64:6379 192.168.100.64 6379 @ mymaster 192.168.100.62 6379 36639:X 07 Oct 2022 22:32:06.866 # +failover-end master mymaster 192.168.100.62 6379 36639:X 07 Oct 2022 22:32:06.867 # +switch-master mymaster 192.168.100.62 6379 192.168.100.63 6379 36639:X 07 Oct 2022 22:32:06.867 * +slave slave 192.168.100.64:6379 192.168.100.64 6379 @ mymaster 192.168.100.63 6379 36639:X 07 Oct 2022 22:32:06.867 * +slave slave 192.168.100.62:6379 192.168.100.62 6379 @ mymaster 192.168.100.63 6379 36639:X 07 Oct 2022 22:32:09.887 # +sdown slave 192.168.100.62:6379 192.168.100.62 6379 @ mymaster 192.168.100.63 6379 36639:X 07 Oct 2022 22:57:44.353 # -sdown slave 192.168.100.62:6379 192.168.100.62 6379 @ mymaster 192.168.100.63 6379 36639:X 07 Oct 2022 22:58:09.164 # +sdown slave 192.168.100.62:6379 192.168.100.62 6379 @ mymaster 192.168.100.63 6379 36639:X 07 Oct 2022 22:58:15.882 # -sdown slave 192.168.100.62:6379 192.168.100.62 6379 @ mymaster 192.168.100.63 6379
Sentinel 运维
手动让主节点下线命令格式
127.0.0.1:26379> sentinel failover <masterName>
范例: 手动故障转移
[root@Rocky_62 ~]#grep ^replica-priority /apps/redis/etc/redis.conf replica-priority 100 [root@Rocky_62 ~]#grep ^replica-priority /apps/redis/etc/redis.conf replica-priority 100 [root@Rocky_62 ~]#sed -i 's/^replica-priority 100/replica-priority 10/' /apps/redis/etc/redis.conf [root@Rocky_62 ~]#grep ^replica-priority /apps/redis/etc/redis.conf replica-priority 10 #指定优先级,值越小sentinel会优先将之选为新的master,默为值为100 #或者动态修改 [root@Rocky_62 ~]#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> CONFIG GET replica-priority 1) "replica-priority" 2) "100" 127.0.0.1:6379> CONFIG SET replica-priority 99 OK 127.0.0.1:6379> CONFIG GET replica-priority 1) "replica-priority" 2) "99"
应用程序连接 Sentinel
Redis 官方支持多种开发语言的客户端:https://redis.io/clients
客户端连接 Sentinel 工作原理
-
客户端获取 Sentinel 节点集合,选举出一个 Sentinel
-
由这个sentinel 通过masterName 获取master节点信息,客户端通过sentinel get-master-addr-byname master-name这个api来获取对应主节点信息
-
客户端发送role指令确认master的信息,验证当前获取的“主节点”是真正的主节点,这样的目的是为了防止故障转移期间主节点的变化
-
客户端保持和Sentinel节点集合的联系,即订阅Sentinel节点相关频道,时刻获取关于主节点的相关信息,获取新的master 信息变化,并自动连接新的master
java 连接Sentinel哨兵
#jedis/pom.xml 配置连接redis <properties> <redishosts> localhost:6379,localhost:6380,localhost:6381,localhost:6382,localhost:6383 ,localhost:6384,localhost:6385</redis-hosts> <sentinelhosts> localhost:26379,localhost:26380,localhost:26381</sentinel-hosts> <clusterhosts> localhost:7379,localhost:7380,localhost:7381,localhost:7382,localhost:7383 ,localhost:7384,localhost:7385</cluster-hosts> <github.global.server>github</github.global.server> </properties>
java客户端连接单机的redis是通过Jedis来实现的,java代码用的时候只要创建Jedis对象就可以建多个Jedis连接池来连接redis,应用程序再直接调用连接池即可连接Redis。而Redis为了保障高可用,服务一般都是Sentinel部署方式,当Redis服务中的主服务挂掉之后,会仲裁出另外一台Slaves服务充当Master。这个时候,我们的应用即使使用了Jedis 连接池,如果Master服务挂了,应用将还是无法连接新的Master服务,为了解决这个问题, Jedis也提供了相应的Sentinel实现,能够在Redis Sentinel主从切换时候,通知应用,把应用连接到新的Master服务。
Redis Sentinel的使用也是十分简单的,只是在JedisPool中添加了Sentinel和MasterName参数,JRedisSentinel底层基于Redis订阅实现Redis主从服务的切换通知,当Reids发生主从切换时,Sentinel会发送通知主动通知Jedis进行连接的切换,JedisSentinelPool在每次从连接池中获取链接对象的时候,都要对连接对象进行检测,如果此链接和Sentinel的Master服务连接参数不一致,则会关闭此连接,重新获取新的Jedis连接对象。
python 连接 Sentinel 哨兵
#!/usr/bin/python3 import redis from redis.sentinel import Sentinel #连接哨兵服务器(主机名也可以用域名) sentinel = Sentinel([('192.168.100.62', 26379), ('192.168.100.63', 26379), ('192.168.100.64', 26379) ], socket_timeout=0.5) redis_auth_pass='123456' #mymaster 是运维人员配置哨兵模式的数据库名称,实际名称按照个人部署案例来填写 #获取主服务器地址 master = sentinel.discover_master('mymaster') print(master) #获取从服务器地址 slave = sentinel.discover_slaves('mymaster') print(slave) #获取主服务器进行写入 master = sentinel.master_for('mymaster', socket_timeout=0.5, password=redis_auth_pass, db=0) w_ret = master.set('name', 'wang') #输出:True #获取从服务器进行读取(默认是round-roubin) slave = sentinel.slave_for('mymaster', socket_timeout=0.5, password=redis_auth_pass, db=0) r_ret = slave.get('name') print(r_ret) #输出:wang
Redis Cluster
Redis Cluster 介绍
使用哨兵sentinel 只能解决Redis高可用问题,实现Redis的自动故障转移,但仍然无法解决Redis Master
单节点的性能瓶颈问题
为了解决单机性能的瓶颈,提高Redis 服务整体性能,可以使用分布式集群的解决方案
早期 Redis 分布式集群部署方案:
- 客户端分区:由客户端程序自己实现写入分配、高可用管理和故障转移等,对客户端的开发实现较为
复杂 - 代理服务:客户端不直接连接Redis,而先连接到代理服务,由代理服务实现相应读写分配,当前代
理服务都是第三方实现.此方案中客户端实现无需特殊开发,实现容易,但是代理服务节点仍存有单点
故障和性能瓶颈问题。比如:豌豆荚开发的 codis
Redis 3.0 版本之后推出无中心架构的 Redis Cluster ,支持多个master节点并行写入和故障的自动转移
动能.
Redis cluster 架构
Redis cluster 架构
Redis cluster 需要至少 3个master节点才能实现,slave节点数量不限,当然一般每个master都至少对应的
有一个slave节点
如果有三个主节点采用哈希槽 hash slot 的方式来分配16384个槽位 slot
此三个节点分别承担的slot 区间可以是如以下方式分配
节点M1 0-5460 节点M2 5461-10922 节点M3 10923-16383
Redis cluster的工作原理
数据分区
如果是单机存储的话,直接将数据存放在单机redis就行了。但是如果是集群存储,就需要考虑到数据分
区了。
数据分区通常采取顺序分布和hash分布。
分布方式 | 顺序分布 | 哈希分布 |
---|---|---|
数据分散度 | 分布倾斜 | 分布散列 |
顺序访问 | 支持 | 不支持 |
顺序分布保障了数据的有序性,但是离散性低,可能导致某个分区的数据热度高,其他分区数据的热度
低,分区访问不均衡。
哈希分布也分为多种分布方式,比如区域哈希分区,一致性哈希分区等。而redis cluster采用的是虚拟
槽分区的方式。
虚拟槽分区
redis cluster设置有0~16383的槽,每个槽映射一个数据子集,通过hash函数,将数据存放在不同的槽
位中,每个集群的节点保存一部分的槽。
每个key存储时,先经过哈希函数CRC16(key)得到一个整数,然后整数与16384取余,得到槽的数值,
然后找到对应的节点,将数据存放入对应的槽中
集群通信
但是寻找槽的过程并不是一次就命中的,比如上图key将要存放在14396槽中,但是并不是一下就锁定了
node3节点,可能先去询问node1,然后才访问node3。
而集群中节点之间的通信,保证了最多两次就能命中对应槽所在的节点。因为在每个节点中,都保存了
其他节点的信息,知道哪个槽由哪个节点负责。这样即使第一次访问没有命中槽,但是会通知客户端,
该槽在哪个节点,这样访问对应节点就能精准命中。
- 节点A对节点B发送一个meet操作,B返回后表示A和B之间能够进行沟通。
- 节点A对节点C发送meet操作,C返回后,A和C之间也能进行沟通。
- 然后B根据对A的了解,就能找到C,B和C之间也建立了联系。
- 直到所有节点都能建立联系。
这样每个节点都能互相知道对方负责哪些槽。
集群伸缩
集群并不是建立之后,节点数就固定不变的,也会有新的节点加入集群或者集群中的节点下线,这就是
集群的扩容和缩容。但是由于集群节点和槽息息相关,所以集群的伸缩也对应了槽和数据的迁移
集群扩容
当有新的节点准备好加入集群时,这个新的节点还是孤立节点,加入有两种方式。一个是通过集群节点
执行命令来和孤立节点握手,另一个则是使用脚本来添加节点。
- cluster_node_ip:port: cluster meet ip port new_node_ip:port
- redis-trib.rb add-node new_node_ip:port cluster_node_ip:port
通常这个新的节点有两种身份,要么作为主节点,要么作为从节点:
- 主节点:分摊槽和数据
- 从节点:作故障转移备份
其中槽的迁移有以下步骤:
集群缩容
下线节点的流程如下:
- 判断该节点是否持有槽,如果未持有槽就跳转到下一步,持有槽则先迁移槽到其他节点
- 通知其他节点(cluster forget)忘记该下线节点
- 关闭下线节点的服务
需要注意的是如果先下线主节点,再下线从节点,会进行故障转移,所以要先下线从节点。
故障转移
除了手动下线节点外,也会面对突发故障。下面提到的主要是主节点的故障,因为从节点的故障并不影
响主节点工作,对应的主节点只会记住自己哪个从节点下线了,并将信息发送给其他节点。故障的从节
点重连后,继续官复原职,复制主节点的数据。
只有主节点才需要进行故障转移。在之前学习主从复制时,我们需要使用redis sentinel来实现故障转
移。而redis cluster则不需要redis sentinel,其自身就具备了故障转移功能。
根据前面我们了解到,节点之间是会进行通信的,节点之间通过ping/pong交互消息,所以借此就能发
现故障。集群节点发现故障同样是有主观下线和客观下线的
主观下线
对于每个节点有一个故障列表,故障列表维护了当前节点接收到的其他所有节点的信息。当半数以上的
持有槽的主节点都标记某个节点主观下线,就会尝试客观下线。
客观下线
故障转移
集群同样具备了自动转移故障的功能,和哨兵有些类似,在进行客观下线之后,就开始准备让故障节点
的从节点“上任”了。
首先是进行资格检查,只有具备资格的从节点才能参加选举:
- 故障节点的所有从节点检查和故障主节点之间的断线时间
- 超过cluster-node-timeout * cluster-slave-validati-factor(默认10)则取消选举资格
然后是准备选举顺序,不同偏移量的节点,参与选举的顺位不同。offset最大的slave节点,选举顺位最
高,最优先选举。而offset较低的slave节点,要延迟选举。
当有从节点参加选举后,主节点收到信息就开始投票。偏移量最大的节点,优先参与选举就更大可能获
得最多的票数,称为主节点。
当从节点走马上任变成主节点之后,就要开始进行替换主节点:
- 让该slave节点执行slaveof no one变为master节点
- 将故障节点负责的槽分配给该节点
- 向集群中其他节点广播Pong消息,表明已完成故障转移
- 故障节点重启后,会成为new_master的slave节点
Redis Cluster 部署架构说明
测试环境:3台服务器,每台服务器启动6379和6380两个redis 服务实例,适用于测试环境
生产环境:6台服务器,分别是三组master/slave,适用于生产环境
#集群节点 192.168.100.60 192.168.100.61 192.168.100.62 192.168.100.63 192.168.100.64 192.168.100.65 #预留服务器扩展使用 192.168.100.66 192.168.100.67
说明:Redis 5.X 和之前版本相比有较大变化,以下分别介绍两个版本5.X和4.X的配置
部署方式介绍
redis cluster 有多种部署方法
-
原生命令安装
- 理解Redis Cluster架构
- 生产环境不使用
-
官方工具安装
- 高效、准确
- 生产环境可以使用
-
自主研发
- 可以实现可视化的自动化部署
实战案例:基于Redis 5 以上版本的 redis cluster 部署
官方文档:
https://redis.io/topics/cluster-tutorial
redis cluster 相关命令
范例: 查看 --cluster 选项帮助
[root@Rocky_62 ~]#redis-cli --cluster help Cluster Manager Commands: create host1:port1 ... hostN:portN --cluster-replicas <arg> check host:port --cluster-search-multiple-owners info host:port fix host:port --cluster-search-multiple-owners --cluster-fix-with-unreachable-masters reshard host:port --cluster-from <arg> --cluster-to <arg> --cluster-slots <arg> --cluster-yes --cluster-timeout <arg> --cluster-pipeline <arg> --cluster-replace rebalance host:port --cluster-weight <node1=w1...nodeN=wN> --cluster-use-empty-masters --cluster-timeout <arg> --cluster-simulate --cluster-pipeline <arg> --cluster-threshold <arg> --cluster-replace add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id <arg> del-node host:port node_id call host:port command arg arg .. arg --cluster-only-masters --cluster-only-replicas set-timeout host:port milliseconds import host:port --cluster-from <arg> --cluster-from-user <arg> --cluster-from-pass <arg> --cluster-from-askpass --cluster-copy --cluster-replace backup host:port backup_directory help For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster. Cluster Manager Options: --cluster-yes Automatic yes to cluster commands prompts
范例: 查看CLUSTER 指令的帮助
[root@Rocky_60 ~]#redis-cli -a 123456 CLUSTER HELP Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 1) CLUSTER <subcommand> [<arg> [value] [opt] ...]. Subcommands are: 2) ADDSLOTS <slot> [<slot> ...] 3) Assign slots to current node. 4) BUMPEPOCH 5) Advance the cluster config epoch. 6) COUNT-FAILURE-REPORTS <node-id> 7) Return number of failure reports for <node-id>. 8) COUNTKEYSINSLOT <slot> 9) Return the number of keys in <slot>. 10) DELSLOTS <slot> [<slot> ...] 11) Delete slots information from current node. 12) FAILOVER [FORCE|TAKEOVER] 13) Promote current replica node to being a master. 14) FORGET <node-id> 15) Remove a node from the cluster. 16) GETKEYSINSLOT <slot> <count> 17) Return key names stored by current node in a slot. 18) FLUSHSLOTS 19) Delete current node own slots information. 20) INFO 21) Return information about the cluster. 22) KEYSLOT <key> 23) Return the hash slot for <key>. 24) MEET <ip> <port> [<bus-port>] 25) Connect nodes into a working cluster. 26) MYID 27) Return the node id. 28) NODES 29) Return cluster configuration seen by node. Output format: 30) <id> <ip:port> <flags> <master> <pings> <pongs> <epoch> <link> <slot> ... 31) REPLICATE <node-id> 32) Configure current node as replica to <node-id>. 33) RESET [HARD|SOFT] 34) Reset current node (default: soft). 35) SET-CONFIG-EPOCH <epoch> 36) Set config epoch of current node. 37) SETSLOT <slot> (IMPORTING|MIGRATING|STABLE|NODE <node-id>) 38) Set slot state. 39) REPLICAS <node-id> 40) Return <node-id> replicas. 41) SAVECONFIG 42) Force saving cluster configuration on disk. 43) SLOTS 44) Return information about slots range mappings. Each range is made of: 45) start, end, master and replicas IP addresses, ports and ids 46) HELP 47) Prints this help.
创建 redis cluster集群的环境准备
-
每个Redis 节点采用相同的相同的Redis版本、相同的密码、硬件配置
-
所有Redis服务器必须没有任何数据
-
准备六台主机,地址如下:
192.168.100.60 192.168.100.61 192.168.100.62 192.168.100.63 192.168.100.64 192.168.100.65
启用 redis cluster 配置
所有6台主机都执行以下配置
#所有主机脚本编译安装 REDIS_VERSION=redis-6.2.7 #REDIS_VERSION=redis-4.0.14 PASSWORD=123456 INSTALL_DIR=/apps/redis CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'` . /etc/os-release color () { RES_COL=60 MOVE_TO_COL="echo -en \\033[${RES_COL}G" SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_WARNING="echo -en \\033[1;33m" SETCOLOR_NORMAL="echo -en \E[0m" echo -n "$1" && $MOVE_TO_COL echo -n "[" if [ $2 = "success" -o $2 = "0" ] ;then ${SETCOLOR_SUCCESS} echo -n $" OK " elif [ $2 = "failure" -o $2 = "1" ] ;then ${SETCOLOR_FAILURE} echo -n $"FAILED" else ${SETCOLOR_WARNING} echo -n $"WARNING" fi ${SETCOLOR_NORMAL} echo -n "]" echo } prepare(){ if [ $ID = "centos" -o $ID = "rocky" ];then yum -y install gcc make jemalloc-devel systemd-devel else apt update apt -y install gcc make libjemalloc-dev libsystemd-dev fi if [ $? -eq 0 ];then color "安装软件包成功" 0 else color "安装软件包失败,请检查网络配置" 1 exit fi } install() { if [ ! -f ${REDIS_VERSION}.tar.gz ];then wget http://download.redis.io/releases/${REDIS_VERSION}.tar.gz || { color "Redis 源码下载失败" 1 ; exit; } fi tar xf ${REDIS_VERSION}.tar.gz -C /usr/local/src cd /usr/local/src/${REDIS_VERSION} make -j $CUPS USE_SYSTEMD=yes PREFIX=${INSTALL_DIR} install && color "Redis 编译安装完成" 0 || { color "Redis 编译安装失败" 1 ;exit ; } ln -s ${INSTALL_DIR}/bin/redis-* /usr/bin/ mkdir -p ${INSTALL_DIR}/{etc,log,data,run} cp redis.conf ${INSTALL_DIR}/etc/ sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e "/# requirepass/a requirepass $PASSWORD" -e "/^dir .*/c dir ${INSTALL_DIR}/data/" -e "/logfile .*/c logfile ${INSTALL_DIR}/log/redis-6379.log" -e "/^pidfile .*/c pidfile ${INSTALL_DIR}/run/redis_6379.pid" ${INSTALL_DIR}/etc/redis.conf if id redis &> /dev/null ;then color "Redis 用户已存在" 1 else useradd -r -s /sbin/nologin redis color "Redis 用户创建成功" 0 fi chown -R redis.redis ${INSTALL_DIR} cat >> /etc/sysctl.conf <<EOF net.core.somaxconn = 1024 vm.overcommit_memory = 1 EOF sysctl -p if [ $ID = "centos" -o $ID = "rocky" ];then echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local chmod +x /etc/rc.d/rc.local /etc/rc.d/rc.local else echo -e '#!/bin/bash\necho never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local chmod +x /etc/rc.local /etc/rc.local fi cat > /lib/systemd/system/redis.service <<EOF [Unit] Description=Redis persistent key-value database After=network.target [Service] ExecStart=${INSTALL_DIR}/bin/redis-server ${INSTALL_DIR}/etc/redis.conf --supervised systemd ExecStop=/bin/kill -s QUIT \$MAINPID Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 LimitNOFILE=1000000 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now redis &> /dev/null if [ $? -eq 0 ];then color "Redis 服务启动成功,Redis信息如下:" 0 else color "Redis 启动失败" 1 exit fi sleep 2 redis-cli -a $PASSWORD INFO Server 2> /dev/null } prepare install
每个节点修改redis配置,必须开启cluster功能的参数
#手动修改配置文件 [root@redis-node1 ~]vim /etc/redis.conf bind 0.0.0.0 masterauth 123456 #建议配置,否则后期的master和slave主从复制无法成功,还需再配置 requirepass 123456 cluster-enabled yes #取消此行注释,必须开启集群,开启后 redis 进程会有cluster标识 cluster-config-file nodes-6379.conf #取消此行注释,此为集群状态数据文件,记录主从关系 及slot范围信息,由redis cluster 集群自动创建和维护 cluster-require-full-coverage no #默认值为yes,设为no可以防止一个节点不可用导致整 个cluster不可用 #如果是编译安装可以执行下面操作 [root@Rocky_60 ~]#sed -i.bak -e '/masterauth/a masterauth 123456' -e '/# cluster-enabled yes/a cluster-enabled yes' -e '/# cluster-config-file nodes-6379.conf/a cluster-config-file nodes-6379.conf' -e '/# cluster-require-full-coverage/c cluster-require-full-coverage no' /apps/redis/etc/redis.conf #查看是否配置成功 [root@Rocky_60 ~]#grep -E '^(bind|masterauth|requirepass|cluster-enabled|cluster-config-file|cluster-require-full-coverage)' /apps/redis/etc/redis.conf bind 0.0.0.0 -::1 masterauth 123456 requirepass 123456 cluster-enabled yes cluster-config-file nodes-6379.conf cluster-require-full-coverage no #拷贝配置好的redis.conf到其他主机上 [root@Rocky_61 ~]#scp 192.168.100.60:/apps/redis/etc/redis.conf /apps/redis/etc/redis.conf [root@Rocky_62 ~]#scp 192.168.100.60:/apps/redis/etc/redis.conf /apps/redis/etc/redis.conf [root@Rocky_63 ~]#scp 192.168.100.60:/apps/redis/etc/redis.conf /apps/redis/etc/redis.conf [root@Rocky_64 ~]#scp 192.168.100.60:/apps/redis/etc/redis.conf /apps/redis/etc/redis.conf [root@Rocky_65 ~]#scp 192.168.100.60:/apps/redis/etc/redis.conf /apps/redis/etc/redis.conf #在集群模式下,不能有rdb文件生成,否则无法启动redis服务 [root@Rocky_60 ~]#systemctl enable --now redis [root@Rocky_61 ~]#systemctl enable --now redis [root@Rocky_62 ~]#systemctl enable --now redis [root@Rocky_63 ~]#systemctl enable --now redis [root@Rocky_64 ~]#systemctl enable --now redis [root@Rocky_65 ~]#systemctl enable --now redis [root@Rocky_66 ~]#systemctl enable --now redis
验证当前Redis服务状态:
#开启了16379的cluster的端口,实际的端口=redis port + 10000 [root@Rocky_60 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port LISTEN 0 511 0.0.0.0:6379 LISTEN 0 128 0.0.0.0:22 LISTEN 0 511 0.0.0.0:16379 LISTEN 0 511 [::1]:6379 LISTEN 0 128 [::]:22 LISTEN 0 511 [::1]:16379 #注意进程有[cluster]状态 [root@Rocky_60 ~]#ps -ef|grep redis redis 34590 1 0 22:21 ? 00:00:01 /apps/redis/bin/redis-server 0.0.0.0:6379 [cluster] root 34677 34383 0 22:42 pts/1 00:00:00 grep --color=auto redis
创建集群
#命令redis-cli的选项 --cluster-replicas 1 表示每个master对应一个slave节点 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster create 192.168.100.60:6379 192.168.100.61:6379 192.168.100.62:6379 192.168.100.63:6379 192.168.100.64:6379 192.168.100.65:6379 --cluster-replicas 1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 192.168.100.64:6379 to 192.168.100.60:6379 Adding replica 192.168.100.65:6379 to 192.168.100.61:6379 Adding replica 192.168.100.63:6379 to 192.168.100.62:6379 M: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots:[0-5460] (5461 slots) master M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-10922] (5462 slots) master M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[10923-16383] (5461 slots) master S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 replicates 9693d8397efde93bde348eed5ce976ddab342158 S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 Can I set the above configuration? (type 'yes' to accept): yes #输入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 192.168.100.60:6379) M: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots:[0-5460] (5461 slots) master #已经分配的槽位 1 additional replica(s) #分配了一个slave S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave #slave没有分配槽位 replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e #对应的master的192.168.100.62的 S: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots: (0 slots) slave replicates 9693d8397efde93bde348eed5ce976ddab342158 #对应的master的192.168.100.60的 M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 #对应的master的192.168.100.61的 M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. #所有节点槽位分配完成 >>> Check for open slots... #检查打开的槽位 >>> Check slots coverage... #检查插槽覆盖范围 [OK] All 16384 slots covered. #所有槽位(16384个)分配完成 #观察以上结果,可以看到3组master/slave Adding replica 192.168.100.64:6379 to 192.168.100.60:6379 Adding replica 192.168.100.65:6379 to 192.168.100.61:6379 Adding replica 192.168.100.63:6379 to 192.168.100.62:6379 #如果节点少于3个会出下面提示错误 [root@node1 ~]#redis-cli -a 123456 --cluster create 192.168.100.60:6379 192.168.100.61:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. *** ERROR: Invalid configuration for cluster creation. *** Redis Cluster requires at least 3 master nodes. *** This is not possible with 2 nodes and 0 replicas per node. *** At least 3 nodes are required.
验证集群
查看主从状态
[root@Rocky_60 ~]#redis-cli -a 123456 -c INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:master connected_slaves:1 slave0:ip=192.168.100.64,port=6379,state=online,offset=952,lag=1 master_failover_state:no-failover master_replid:bbc7f23c70f1620089849b4c555b6faca1275261 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:952 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:952 [root@Rocky_61 ~]#redis-cli -a 123456 INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:master connected_slaves:1 slave0:ip=192.168.100.65,port=6379,state=online,offset=1008,lag=1 master_failover_state:no-failover master_replid:faa0c5eb7bd6d57d46e070ca0658d25044d2cfcf master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1008 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1008 [root@Rocky_62 ~]#redis-cli -a 123456 INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:master connected_slaves:1 slave0:ip=192.168.100.63,port=6379,state=online,offset=1050,lag=0 master_failover_state:no-failover master_replid:77d6bfc3fcdfee8083a58505b218bd06bc262957 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1050 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1050 [root@Rocky_63 ~]#redis-cli -a 123456 INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:slave master_host:192.168.100.62 master_port:6379 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_read_repl_offset:1106 slave_repl_offset:1106 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:77d6bfc3fcdfee8083a58505b218bd06bc262957 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1106 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1106 [root@Rocky_64 ~]#redis-cli -a 123456 INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:slave master_host:192.168.100.60 master_port:6379 master_link_status:up master_last_io_seconds_ago:8 master_sync_in_progress:0 slave_read_repl_offset:1176 slave_repl_offset:1176 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:bbc7f23c70f1620089849b4c555b6faca1275261 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1176 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1176 [root@Rocky_65 ~]#redis-cli -a 123456 INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:slave master_host:192.168.100.61 master_port:6379 master_link_status:up master_last_io_seconds_ago:5 master_sync_in_progress:0 slave_read_repl_offset:1232 slave_repl_offset:1232 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:faa0c5eb7bd6d57d46e070ca0658d25044d2cfcf master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1232 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1232
范例: 查看指定master节点的slave节点信息
#对应的就是/apps/redis/data/nodes-6379.conf信息 [root@Rocky_60 ~]#redis-cli -a 123456 cluster nodes Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379@16379 slave e37c774a715b0336b0406c9c3bfd3c4035daac7e 0 1665244626643 3 connected 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379@16379 slave 9693d8397efde93bde348eed5ce976ddab342158 0 1665244628000 1 connected e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379@16379 master - 0 1665244627667 3 connected 10923-16383 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379@16379 slave 253d645d4ddcfd9a8f3d97be5178606e182edfa1 0 1665244629714 2 connected 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379@16379 master - 0 1665244628690 2 connected 5461-10922 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379@16379 myself,master - 0 1665244627000 1 connected 0-5460 #以下命令查看指定master节点的slave节点信息,其中 #253d645d4ddcfd9a8f3d97be5178606e182edfa1 为master节点的ID [root@Rocky_60 ~]#redis-cli -a 123456 cluster slaves 253d645d4ddcfd9a8f3d97be5178606e182edfa1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 1) "5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379@16379 slave 253d645d4ddcfd9a8f3d97be5178606e182edfa1 0 1665244896439 2 connected"
验证集群状态
[root@Rocky_60 ~]#redis-cli -a 123456 CLUSTER INFO Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 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 #3个集群 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:1369 cluster_stats_messages_pong_sent:1374 cluster_stats_messages_sent:2743 cluster_stats_messages_ping_received:1369 cluster_stats_messages_pong_received:1369 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:2743 #查看任意节点的集群状态 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster info 192.168.100.62:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 0 keys | 5461 slots | 1 slaves. 192.168.100.60:6379 (9693d839...) -> 0 keys | 5461 slots | 1 slaves. 192.168.100.61:6379 (253d645d...) -> 0 keys | 5462 slots | 1 slaves. [OK] 0 keys in 3 masters. 0.00 keys per slot on average.
查看对应关系
[root@Rocky_60 ~]#redis-cli -a 123456 CLUSTER NODES Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379@16379 slave e37c774a715b0336b0406c9c3bfd3c4035daac7e 0 1665245176000 3 connected 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379@16379 slave 9693d8397efde93bde348eed5ce976ddab342158 0 1665245176878 1 connected e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379@16379 master - 0 1665245175000 3 connected 10923-16383 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379@16379 slave 253d645d4ddcfd9a8f3d97be5178606e182edfa1 0 1665245175000 2 connected 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379@16379 master - 0 1665245176000 2 connected 5461-10922 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379@16379 myself,master - 0 1665245173000 1 connected 0-5460 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.60:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.60:6379 (9693d839...) -> 0 keys | 5461 slots | 1 slaves. 192.168.100.62:6379 (e37c774a...) -> 0 keys | 5461 slots | 1 slaves. 192.168.100.61:6379 (253d645d...) -> 0 keys | 5462 slots | 1 slaves. [OK] 0 keys in 3 masters. 0.00 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.60:6379) M: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots: (0 slots) slave replicates 9693d8397efde93bde348eed5ce976ddab342158 M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
测试集群写入数据
redis cluster 写入key
#经过算法计算,当前key的槽位需要写入指定的node [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.62 SET key1 values1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. (error) MOVED 9189 192.168.100.61:6379 #槽位不在当前node所以无法写入 #指定槽位对应node可写入 [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.61 SET key1 values1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. OK [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.61 get key1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. "values1" #对应的slave节点可以KEYS *,但GET key1失败,可以到master上执行GET key1 [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.65 KEYS "*" Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 1) "key1" [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.65 get key1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. (error) MOVED 9189 192.168.100.61:6379
redis cluster 计算key所属的slot
[root@Rocky_60 ~]#redis-cli -h 192.168.100.61 -a 123456 --no-auth-warning cluster nodes 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379@16379 master - 0 1665245945129 1 connected 0-5460 e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379@16379 master - 0 1665245942061 3 connected 10923-16383 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379@16379 slave 253d645d4ddcfd9a8f3d97be5178606e182edfa1 0 1665245943000 2 connected ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379@16379 slave e37c774a715b0336b0406c9c3bfd3c4035daac7e 0 1665245944105 3 connected 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379@16379 myself,master - 0 1665245941000 2 connected 5461-10922 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379@16379 slave 9693d8397efde93bde348eed5ce976ddab342158 0 1665245943084 1 connected #计算得到hello对应的slot [root@Rocky_60 ~]#redis-cli -h 192.168.100.60 -a 123456 --no-auth-warning cluster keyslot hello (integer) 866 [root@Rocky_60 ~]#redis-cli -h 192.168.100.60 -a 123456 --no-auth-warning set hello zhang OK [root@Rocky_60 ~]#redis-cli -h 192.168.100.60 -a 123456 --no-auth-warning cluster keyslot name (integer) 5798 [root@Rocky_60 ~]#redis-cli -h 192.168.100.60 -a 123456 --no-auth-warning set name long (error) MOVED 5798 192.168.100.61:6379 [root@Rocky_60 ~]#redis-cli -h 192.168.100.61 -a 123456 --no-auth-warning set name long OK [root@Rocky_60 ~]#redis-cli -h 192.168.100.61 -a 123456 --no-auth-warning get name "long" #使用选项-c 以集群模式连接 [root@Rocky_60 ~]#redis-cli -c -h 192.168.100.60 -a 123456 --no-auth-warning 192.168.100.60:6379> cluster keyslot linux (integer) 12299 192.168.100.60:6379> set linux love -> Redirected to slot [12299] located at 192.168.100.62:6379 OK 192.168.100.62:6379> get linux "love" 192.168.100.62:6379> exit [root@Rocky_60 ~]#redis-cli -h 192.168.100.62 -a 123456 --no-auth-warning get linux "love"
python 程序实现Redis Cluster 访问
官网:
https://github.com/Grokzen/redis-py-cluster
范例:
[root@Rocky_50 ~]#dnf -y install python3 [root@Rocky_50 ~]#pip3 install redis-py-cluster [root@Rocky_50 ~]#vim redis_cluster_test.py [root@Rocky_50 ~]#cat ./redis_cluster_test.py #!/usr/bin/env python3 from rediscluster import RedisCluster if __name__ == '__main__': startup_nodes = [ {"host":"192.168.100.60", "port":6379}, {"host":"192.168.100.61", "port":6379}, {"host":"192.168.100.62", "port":6379}, {"host":"192.168.100.63", "port":6379}, {"host":"192.168.100.64", "port":6379}, {"host":"192.168.100.65", "port":6379}] try: redis_conn= RedisCluster(startup_nodes=startup_nodes,password='123456', decode_responses=True) except Exception as e: print(e) for i in range(0, 10000): redis_conn.set('key'+str(i),'value'+str(i)) print('key'+str(i)+':',redis_conn.get('key'+str(i))) [root@Rocky_100 ~]#python3 redis_cluster_test.py ...... key9998: value9998 key9999: value9999 #验证数据 192.168.100.60:6379> DBSIZE (integer) 3332 192.168.100.60:6379> get key1 (error) MOVED 9189 192.168.100.61:6379 192.168.100.60:6379> get key2 "value2" [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.61 DBSIZE Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. (integer) 3341 [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.62 DBSIZE Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. (integer) 3330
模拟故障实现故障转移
#模拟192.168.100.60节点出故障,需要相应的数秒故障转移时间 [root@Rocky_60 ~]#tail -f /apps/redis/log/redis-6379.log 34590:M 09 Oct 2022 00:34:55.753 * Background saving terminated with success 34590:M 09 Oct 2022 00:39:56.009 * 100 changes in 300 seconds. Saving... 34590:M 09 Oct 2022 00:39:56.009 * Background saving started by pid 34829 34829:C 09 Oct 2022 00:39:56.017 * DB saved on disk 34829:C 09 Oct 2022 00:39:56.017 * RDB: 0 MB of memory used by copy-on-write 34590:M 09 Oct 2022 00:39:56.111 * Background saving terminated with success 34590:M 09 Oct 2022 08:48:37.841 # Disconnecting timedout replica (streaming sync): 192.168.100.64:6379 34590:M 09 Oct 2022 08:48:37.841 # Connection with replica 192.168.100.64:6379 lost. 34590:M 09 Oct 2022 08:48:47.895 * Replica 192.168.100.64:6379 asks for synchronization 34590:M 09 Oct 2022 08:48:47.895 * Partial resynchronization request from 192.168.100.64:6379 accepted. Sending 0 bytes of backlog starting from offset 141086. #关闭redis运行服务,模拟redis故障 [root@Rocky_60 ~]#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> SHUTDOWN not connected> exit [root@Rocky_60 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* [root@Rocky_60 ~]#redis-cli -a 123456 --cluster info 192.168.100.61:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. Could not connect to Redis at 192.168.100.60:6379: Connection refused 192.168.100.61:6379 (253d645d...) -> 3341 keys | 5462 slots | 1 slaves. 192.168.100.62:6379 (e37c774a...) -> 3330 keys | 5461 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 3332 keys | 5461 slots | 0 slaves. [OK] 10003 keys in 3 masters. 0.61 keys per slot on average. #通过查看集群其他任意节点检查集群状态 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.61:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. Could not connect to Redis at 192.168.100.60:6379: Connection refused 192.168.100.61:6379 (253d645d...) -> 3341 keys | 5462 slots | 1 slaves. 192.168.100.62:6379 (e37c774a...) -> 3330 keys | 5461 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 3332 keys | 5461 slots | 0 slaves. [OK] 10003 keys in 3 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.61:6379) M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[0-5460] (5461 slots) master [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. #查看新master节点状态信息 [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.64 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.64:6379> INFO replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:84abf506a9b13190124d2e67e70a55730699fe7e master_replid2:bbc7f23c70f1620089849b4c555b6faca1275261 master_repl_offset:141603 second_repl_offset:141604 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:141603 #恢复故障节点192.168.100.60自动成为slave节点 [root@Rocky_60 ~]#systemctl start redis #查看自动生成的配置文件,可以查看node2自动成为slave节点 [root@Rocky_60 ~]#tail /apps/redis/data/nodes-6379.conf e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379@16379 master - 1665277255542 1665277255496 3 connected 10923-16383 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379@16379 myself,slave 88c7caaa8381bd46cf840aca73462ce88ea095d6 0 1665277255497 7 connected 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379@16379 master - 1665277255542 1665277255497 2 connected 5461-10922 ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379@16379 slave e37c774a715b0336b0406c9c3bfd3c4035daac7e 1665277255542 1665277255496 3 connected 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379@16379 slave 253d645d4ddcfd9a8f3d97be5178606e182edfa1 0 1665277255497 2 connected 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379@16379 master - 0 1665277255496 7 connected 0-5460 vars currentEpoch 7 lastVoteEpoch 0 #查看master节点状态信息 [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.64 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.64:6379> INFO replication # Replication role:master connected_slaves:1 slave0:ip=192.168.100.60,port=6379,state=online,offset=141813,lag=0 master_failover_state:no-failover master_replid:84abf506a9b13190124d2e67e70a55730699fe7e master_replid2:bbc7f23c70f1620089849b4c555b6faca1275261 master_repl_offset:141813 second_repl_offset:141604 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:141813
Redis cluster 管理
集群扩容
当前客户量激增,现有的Redis cluster架构已经无法满足越来越高的并发访问请求,为解决此问题,新购
置两台服务器,要求将其动态添加到现有集群,但不能影响业务的正常访问。
注意: 生产环境一般建议master节点为奇数个,比如:3,5,7,以防止脑裂现象
添加节点准备
增加Redis 新节点,需要与之前的Redis node版本和配置一致,然后分别再启动两台Redis node,应为
一主一从。
#配置192.168.100.66节点 #redis安装为脚本编译安装,参考:6.3.3.2.启用 redis cluster 配置 [root@Rocky_66 ~]#scp 192.168.100.64:/apps/redis/etc/redis.conf /apps/redis/etc/redis.conf [root@Rocky_66 ~]#grep -E '^(bind|masterauth|requirepass|cluster-enabled|cluster-config-file|cluster-require-full-coverage)' /apps/redis/etc/redis.conf bind 0.0.0.0 -::1 masterauth 123456 requirepass 123456 cluster-enabled yes cluster-config-file nodes-6379.conf cluster-require-full-coverage no [root@Rocky_66 ~]#systemctl enable --now redis #配置192.168.100.67节点 #redis安装为脚本编译安装,参考:6.3.3.2.启用 redis cluster 配置 [root@Rocky_67 ~]#scp 192.168.100.64:/apps/redis/etc/redis.conf /apps/redis/etc/redis.conf [root@Rocky_67 ~]#grep -E '^(bind|masterauth|requirepass|cluster-enabled|cluster-config-file|cluster-require-full-coverage)' /apps/redis/etc/redis.conf bind 0.0.0.0 -::1 masterauth 123456 requirepass 123456 cluster-enabled yes cluster-config-file nodes-6379.conf cluster-require-full-coverage no [root@Rocky_67 ~]#systemctl enable --now redis
添加新的master节点到集群
使用以下命令添加新节点,要添加的新redis节点IP和端口添加到的已有的集群中任意节点的IP:端口
add-node new_host:new_port existing_host:existing_port [--slave --master-id <arg>] #说明: new_host:new_port #指定新添加的主机的IP和端口 existing_host:existing_port #指定已有的集群中任意节点的IP和端口
Redis 3/4 版本的添加命令:
#把新的Redis 节点10.0.0.37添加到当前Redis集群当中。 [root@redis-node1 ~]#redis-trib.rb add-node 10.0.0.37:6379 10.0.0.7:6379 [root@redis-node1 ~]#redis-trib.rb info 10.0.0.7:6379 10.0.0.7:6379 (29a83275...) -> 3331 keys | 5461 slots | 1 slaves. 10.0.0.37:6379 (12ca273a...) -> 0 keys | 0 slots | 0 slaves. 10.0.0.27:6379 (90b20613...) -> 3329 keys | 5461 slots | 1 slaves. 10.0.0.17:6379 (fb34c3a7...) -> 3340 keys | 5462 slots | 1 slaves. [OK] 10000 keys in 4 masters. 0.61 keys per slot on average.
Redis 5 以上版本的添加命令:
#将一台新的主机10.0.0.68加入集群,以下示例中10.0.0.58可以是任意存在的集群节点 #redis-cli -a 123456 --cluster add-node 192.168.100.66:6379 <当前任意集群节点>:6379 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster add-node 192.168.100.66:6379 192.168.100.61:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Adding node 192.168.100.66:6379 to cluster 192.168.100.61:6379 >>> Performing Cluster Check (using node 192.168.100.61:6379) M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. >>> Send CLUSTER MEET to node 192.168.100.66:6379 to make it join the cluster. [OK] New node added correctly. #观察到该节点已经加入成功,但此节点上没有slot位,也无从节点,而且新的节点是master [root@Rocky_60 ~]#redis-cli -a 123456 --cluster info 192.168.100.60:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 3330 keys | 5461 slots | 1 slaves. 192.168.100.61:6379 (253d645d...) -> 3341 keys | 5462 slots | 1 slaves. 192.168.100.66:6379 (37f5cfe3...) -> 0 keys | 0 slots | 0 slaves. 192.168.100.64:6379 (88c7caaa...) -> 3332 keys | 5461 slots | 1 slaves. [OK] 10003 keys in 4 masters. 0.61 keys per slot on average. [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.60:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 3330 keys | 5461 slots | 1 slaves. 192.168.100.61:6379 (253d645d...) -> 3341 keys | 5462 slots | 1 slaves. 192.168.100.66:6379 (37f5cfe3...) -> 0 keys | 0 slots | 0 slaves. 192.168.100.64:6379 (88c7caaa...) -> 3332 keys | 5461 slots | 1 slaves. [OK] 10003 keys in 4 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.60:6379) S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) M: 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379 slots: (0 slots) master S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. [root@Rocky_60 ~]#cat /apps/redis/data/nodes-6379.conf e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379@16379 master - 1665277255542 1665277255496 3 connected 10923-16383 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379@16379 myself,slave 88c7caaa8381bd46cf840aca73462ce88ea095d6 0 1665277255497 7 connected 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379@16379 master - 1665277255542 1665277255497 2 connected 5461-10922 ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379@16379 slave e37c774a715b0336b0406c9c3bfd3c4035daac7e 1665277255542 1665277255496 3 connected 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379@16379 slave 253d645d4ddcfd9a8f3d97be5178606e182edfa1 0 1665277255497 2 connected 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379@16379 master - 0 1665277255496 7 connected 0-5460 vars currentEpoch 7 lastVoteEpoch 0 #和上面显示结果一样 [root@Rocky_60 ~]#redis-cli -a 123456 CLUSTER NODES Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379@16379 master - 0 1665282302511 3 connected 10923-16383 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379@16379 myself,slave 88c7caaa8381bd46cf840aca73462ce88ea095d6 0 1665282300000 7 connected 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379@16379 master - 0 1665282300463 2 connected 5461-10922 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379@16379 master - 0 1665282300000 0 connected ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379@16379 slave e37c774a715b0336b0406c9c3bfd3c4035daac7e 0 1665282299000 3 connected 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379@16379 slave 253d645d4ddcfd9a8f3d97be5178606e182edfa1 0 1665282301000 2 connected 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379@16379 master - 0 1665282301487 7 connected 0-5460 #查看集群状态 [root@Rocky_60 ~]#redis-cli -a 123456 CLUSTER INFO Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:7 cluster_size:3 cluster_current_epoch:7 cluster_my_epoch:7 cluster_stats_messages_ping_sent:4957 cluster_stats_messages_pong_sent:4890 cluster_stats_messages_sent:9847 cluster_stats_messages_ping_received:4890 cluster_stats_messages_pong_received:4957 cluster_stats_messages_update_received:2 cluster_stats_messages_received:9849
在新的master上重新分配槽位
新的node节点加到集群之后,默认是master节点,但是没有slots,需要重新分配,否则没有槽位将无法访问
注意: 重新分配槽位需要清空数据,所以需要先备份数据,扩展后再恢复数据
Redis 3/4 版本命令:
[root@redis-node1 ~]# redis-trib.rb check 10.0.0.67:6379 #当前状态 [root@redis-node1 ~]# redis-trib.rb reshard <任意节点>:6379 #重新分片 [root@redis-node1 ~]# redis-trib.rb fix 10.0.0.67:6379 #如果迁移失败使用此命令修复集群
Redis 5以上版本命令:
#redis-cli -a 123456 --cluster reshard <当前任意集群节点>:6379 [root@Rocky_60 ~]# redis-cli -a 123456 --cluster reshard 192.168.100.65:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Performing Cluster Check (using node 10.0.0.68:6379) M: d6e2eca6b338b717923f64866bd31d42e52edc98 192.168.100.60:6379 slots: (0 slots) master M: d34da8666a6f587283a1c2fca5d13691407f9462 10.0.0.28:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: d04e524daec4d8e22bdada7f21a9487c2d3e1057 10.0.0.48:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) M: cb028b83f9dc463d732f6e76ca6bbcd469d948a7 10.0.0.8:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 99720241248ff0e4c6fa65c2385e92468b3b5993 10.0.0.18:6379 slots: (0 slots) slave replicates d04e524daec4d8e22bdada7f21a9487c2d3e1057 M: f67f1c02c742cd48d3f48d8c362f9f1b9aa31549 10.0.0.78:6379 slots: (0 slots) master S: f9adcfb8f5a037b257af35fa548a26ffbadc852d 10.0.0.38:6379 slots: (0 slots) slave replicates cb028b83f9dc463d732f6e76ca6bbcd469d948a7 S: 9875b50925b4e4f29598e6072e5937f90df9fc71 10.0.0.58:6379 slots: (0 slots) slave replicates d34da8666a6f587283a1c2fca5d13691407f9462 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. How many slots do you want to move (from 1 to 16384)?4096 #新分配多少个槽位 =16384/master个数 What is the receiving node ID? d6e2eca6b338b717923f64866bd31d42e52edc98 #新的 master的ID Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1: all #输入all,将哪些源主机的槽位分配给新的节点,all是自动在所有的redis node选择划分,如果是从redis cluster删除某个主机可以使用此方式将指定主机上的槽位全部移动到别的 redis主机 ...... Do you want to proceed with the proposed reshard plan (yes/no)? yes #确认分配 ...... Moving slot 12280 from 10.0.0.28:6379 to 10.0.0.68:6379: . Moving slot 12281 from 10.0.0.28:6379 to 10.0.0.68:6379: . Moving slot 12282 from 10.0.0.28:6379 to 10.0.0.68:6379: Moving slot 12283 from 10.0.0.28:6379 to 10.0.0.68:6379: .. Moving slot 12284 from 10.0.0.28:6379 to 10.0.0.68:6379: Moving slot 12285 from 10.0.0.28:6379 to 10.0.0.68:6379: . Moving slot 12286 from 10.0.0.28:6379 to 10.0.0.68:6379: Moving slot 12287 from 10.0.0.28:6379 to 10.0.0.68:6379: .. #确定slot分配成功 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.62:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 2501 keys | 4096 slots | 1 slaves. 192.168.100.66:6379 (37f5cfe3...) -> 2476 keys | 4096 slots | 0 slaves. 192.168.100.61:6379 (253d645d...) -> 2515 keys | 4096 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 2511 keys | 4096 slots | 1 slaves. [OK] 10003 keys in 4 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.62:6379) M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[12288-16383] (4096 slots) master 1 additional replica(s) M: 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379 slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master #可看到4096个slots S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[6827-10922] (4096 slots) master 1 additional replica(s) S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[1365-5460] (4096 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
为新的master指定新的slave节点
当前Redis集群中新的master节点存单点问题,还需要给其添加一个对应slave节点,实现高可用功能
有两种方式:
方法1:在新加节点到集群时,直接将之设置为slave
Redis 3/4 添加命令:
redis-trib.rb add-node --slave --master-id 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.67:6379 <任意集群节点>:6379
Redis 5 以上版本添加命令:
redis-cli -a 123456 --cluster add-node 192.168.100.67:6379 <任意集群节点>:6379 --cluster-slave --cluster-master-id 37f5cfe3aa8de68b6a439e55567971619573e36c
范例:
#查看当前状态 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.62:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 2501 keys | 4096 slots | 1 slaves. 192.168.100.66:6379 (37f5cfe3...) -> 2476 keys | 4096 slots | 0 slaves. 192.168.100.61:6379 (253d645d...) -> 2515 keys | 4096 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 2511 keys | 4096 slots | 1 slaves. [OK] 10003 keys in 4 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.62:6379) M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[12288-16383] (4096 slots) master 1 additional replica(s) M: 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379 slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[6827-10922] (4096 slots) master 1 additional replica(s) S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[1365-5460] (4096 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. #直接加为slave节点 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster add-node 192.168.100.67:6379 192.168.100.62:6379 --cluster-slave --cluster-master-id 37f5cfe3aa8de68b6a439e55567971619573e36c Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Adding node 192.168.100.67:6379 to cluster 192.168.100.62:6379 >>> Performing Cluster Check (using node 192.168.100.62:6379) M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[12288-16383] (4096 slots) master 1 additional replica(s) M: 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379 slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[6827-10922] (4096 slots) master 1 additional replica(s) S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[1365-5460] (4096 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. >>> Send CLUSTER MEET to node 192.168.100.67:6379 to make it join the cluster. Waiting for the cluster to join >>> Configure node as replica of 192.168.100.66:6379. [OK] New node added correctly. #验证是否成功 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.60:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 2501 keys | 4096 slots | 1 slaves. 192.168.100.61:6379 (253d645d...) -> 2515 keys | 4096 slots | 1 slaves. 192.168.100.66:6379 (37f5cfe3...) -> 2476 keys | 4096 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 2511 keys | 4096 slots | 1 slaves. [OK] 10003 keys in 4 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.60:6379) S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 S: 712b72558c88279da8f3b31253195b1cc4ba95f1 192.168.100.67:6379 slots: (0 slots) slave replicates 37f5cfe3aa8de68b6a439e55567971619573e36c M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[12288-16383] (4096 slots) master 1 additional replica(s) M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[6827-10922] (4096 slots) master 1 additional replica(s) M: 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379 slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master 1 additional replica(s) S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[1365-5460] (4096 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.60 --no-auth-warning cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:8 #8个节点 cluster_size:4 #4组主从 cluster_current_epoch:8 cluster_my_epoch:7 cluster_stats_messages_ping_sent:7895 cluster_stats_messages_pong_sent:7685 cluster_stats_messages_sent:15580 cluster_stats_messages_ping_received:7685 cluster_stats_messages_pong_received:11991 cluster_stats_messages_update_received:7 cluster_stats_messages_received:19683
方法2:先将新节点加入集群,再修改为slave
- 为新的master添加slave节点
Redis 3/4 版本命令:
[root@redis-node1 ~]#redis-trib.rb add-node 192.168.100.67:6379 192.168.100.60:6379
Redis 5 以上版本命令:
#把192.168.100.66:6379添加到集群中: [root@redis-node1 ~]#redis-cli -a 123456 --cluster add-node 192.168.100.67:6379 192.168.100.60:6379
更改新节点更改状态为slave:
需要手动将其指定为某个master的slave,否则其默认角色为master。
[root@redis-node1 ~]#redis-cli -h 192.168.100.67 -p 6379 -a 123456 #登录到新添加节点 192.168.100.67:6380> CLUSTER NODES #查看当前集群节点,找到目标master 的ID 192.168.100.67:6380> CLUSTER REPLICATE 37f5cfe3aa8de68b6a439e55567971619573e36c #将其设 置slave,命令格式为cluster replicate MASTERID 192.168.100.67:6380> CLUSTER NODES #再次查看集群节点状态,验证节点是否已经更改为指定master 的 slave
集群缩容
缩容适用场景:
随着业务萎缩用户量下降明显,和领导商量决定将现有Redis集群的8台主机中下线两台主机挪做它用,缩容
后性能仍能满足当前业务需求
删除节点过程:
扩容时是先添加node到集群,然后再分配槽位,而缩容时的操作相反,是先将被要删除的node上的槽
位迁移到集群中的其他node上,然后 才能再将其从集群中删除,如果一个node上的槽位没有被完全迁
移空,删除该node时也会提示有数据出错导致无法删除。
迁移要删除的master节点上面的槽位到其它master
注意: 被迁移Redis master源服务器必须保证没有数据,否则迁移报错并会被强制中断。
Redis 3/4 版本命令
[root@redis-node1 ~]# redis-trib.rb reshard 192.168.100.60:6379 [root@redis-node1 ~]# redis-trib.rb fix 192.168.100.60:6379 #如果迁移失败使用此命令修复集群
Redis 5版本以上命令
#查看当前状态 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.66:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 2501 keys | 4096 slots | 1 slaves. 192.168.100.61:6379 (253d645d...) -> 2515 keys | 4096 slots | 1 slaves. 192.168.100.66:6379 (37f5cfe3...) -> 2476 keys | 4096 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 2511 keys | 4096 slots | 1 slaves. [OK] 10003 keys in 4 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.60:6379) S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 S: 712b72558c88279da8f3b31253195b1cc4ba95f1 192.168.100.67:6379 slots: (0 slots) slave replicates 37f5cfe3aa8de68b6a439e55567971619573e36c M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[12288-16383] (4096 slots) master 1 additional replica(s) M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[6827-10922] (4096 slots) master 1 additional replica(s) M: 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379 slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master 1 additional replica(s) S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[1365-5460] (4096 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. #连接到任意集群节点,#最后1365个slot从192.168.100.66移动到第一个master节点192.168.100.64上 [root@Rocky_66 ~]#redis-cli -a 123456 --cluster reshard 192.168.100.64:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Performing Cluster Check (using node 192.168.100.64:6379) M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[1365-5460] (4096 slots) master 1 additional replica(s) M: 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379 slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master 1 additional replica(s) S: 712b72558c88279da8f3b31253195b1cc4ba95f1 192.168.100.67:6379 slots: (0 slots) slave replicates 37f5cfe3aa8de68b6a439e55567971619573e36c S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[6827-10922] (4096 slots) master 1 additional replica(s) S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[12288-16383] (4096 slots) master 1 additional replica(s) S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. How many slots do you want to move (from 1 to 16384)? 1365 #共4096/3分别给其它三个master节点 What is the receiving node ID? 88c7caaa8381bd46cf840aca73462ce88ea095d6 #master:192.168.100.64 Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1: 37f5cfe3aa8de68b6a439e55567971619573e36c #输入要删除节点:192.168.100.66 Source node #2: done ............ Moving slot 1357 from 37f5cfe3aa8de68b6a439e55567971619573e36c Moving slot 1358 from 37f5cfe3aa8de68b6a439e55567971619573e36c Moving slot 1359 from 37f5cfe3aa8de68b6a439e55567971619573e36c Moving slot 1360 from 37f5cfe3aa8de68b6a439e55567971619573e36c Moving slot 1361 from 37f5cfe3aa8de68b6a439e55567971619573e36c Moving slot 1362 from 37f5cfe3aa8de68b6a439e55567971619573e36c Moving slot 1363 from 37f5cfe3aa8de68b6a439e55567971619573e36c Moving slot 1364 from 37f5cfe3aa8de68b6a439e55567971619573e36c Do you want to proceed with the proposed reshard plan (yes/no)? yes #非交互式方式 #再将1365个slot从192.168.100.66移动到第二个master节点192.168.100.61上 #转移槽位的id:37f5cfe3aa8de68b6a439e55567971619573e36c #接受槽位的id:253d645d4ddcfd9a8f3d97be5178606e182edfa1 [root@Rocky_66 ~]#redis-cli -a 123456 --cluster reshard 192.168.100.60:6379 --cluster-slots 1365 --cluster-from 37f5cfe3aa8de68b6a439e55567971619573e36c --cluster-to 253d645d4ddcfd9a8f3d97be5178606e182edfa1 --cluster-yes #最后的slot从192.168.100.66移动到第三个master节点192.168.100.62上 [root@Rocky_66 ~]#redis-cli -a 123456 --cluster reshard 192.168.100.60:6379 --cluster-slots 1366 --cluster-from 37f5cfe3aa8de68b6a439e55567971619573e36c --cluster-to e37c774a715b0336b0406c9c3bfd3c4035daac7e --cluster-yes #确认192.168.100.66的所有slot都移走了,上面的slave也自动删除,成为其它master的slave [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.60:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 3331 keys | 5462 slots | 3 slaves. 192.168.100.61:6379 (253d645d...) -> 3340 keys | 5461 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 3332 keys | 5461 slots | 1 slaves. [OK] 10003 keys in 3 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.60:6379) S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 S: 712b72558c88279da8f3b31253195b1cc4ba95f1 192.168.100.67:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[6826],[10923-16383] (5462 slots) master 3 additional replica(s) M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-6825],[6827-10922] (5461 slots) master 1 additional replica(s) S: 37f5cfe3aa8de68b6a439e55567971619573e36c 192.168.100.66:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.62 INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:master connected_slaves:3 slave0:ip=192.168.100.63,port=6379,state=online,offset=255509,lag=1 slave1:ip=192.168.100.67,port=6379,state=online,offset=255509,lag=1 slave2:ip=192.168.100.66,port=6379,state=online,offset=255509,lag=1 master_failover_state:no-failover master_replid:77d6bfc3fcdfee8083a58505b218bd06bc262957 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:255509 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:255509 [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.66 --no-auth-warning cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:8 #集群中8个节点 cluster_size:3 #少了一个主从的slot cluster_current_epoch:11 cluster_my_epoch:11 cluster_stats_messages_ping_sent:20328 cluster_stats_messages_pong_sent:45069 cluster_stats_messages_meet_sent:1 cluster_stats_messages_update_sent:7 cluster_stats_messages_sent:65405 cluster_stats_messages_ping_received:20493 cluster_stats_messages_pong_received:24425 cluster_stats_messages_update_received:5 cluster_stats_messages_received:44923
从集群中删除服务器
上面步骤完成后,槽位已经迁移走,但是节点仍然还属于集群成员,因此还需从集群删除该节点
注意: 删除服务器前,必须清除主机上面的槽位,否则会删除主机失败
Redis 3/4命令:
[root@s~]#redis-trib.rb del-node <任意集群节点的IP>:6379 dfffc371085859f2858730e1f350e9167e287073 #dfffc371085859f2858730e1f350e9167e287073 是删除节点的ID >>> Removing node dfffc371085859f2858730e1f350e9167e287073 from cluster 192.168.7.102:6379 >>> Sending CLUSTER FORGET messages to the cluster... >>> SHUTDOWN the node.
Redis 5以上版本命令:
#redis-cli -a 123456 --cluster del-node <任意集群节点的IP>:6379 37f5cfe3aa8de68b6a439e55567971619573e36c #37f5cfe3aa8de68b6a439e55567971619573e36c是删除节点的ID 192.168.100.66 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster del-node 192.168.100.60:6379 37f5cfe3aa8de68b6a439e55567971619573e36c Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Removing node 37f5cfe3aa8de68b6a439e55567971619573e36c from cluster 192.168.100.60:6379 >>> Sending CLUSTER FORGET messages to the cluster... >>> Sending CLUSTER RESET SOFT to the deleted node. #删除节点后,redis重置软件命令 #删除节点信息 [root@Rocky_66 ~]#rm -f /apps/redis/data/nodes-6379.conf
删除多余的slave节点验证结果
[root@Rocky_66 ~]#redis-cli -a 123456 --cluster check 192.168.100.60:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 3331 keys | 5462 slots | 2 slaves. 192.168.100.61:6379 (253d645d...) -> 3340 keys | 5461 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 3332 keys | 5461 slots | 1 slaves. [OK] 10003 keys in 3 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.60:6379) S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 S: 712b72558c88279da8f3b31253195b1cc4ba95f1 192.168.100.67:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[6826],[10923-16383] (5462 slots) master 2 additional replica(s) M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-6825],[6827-10922] (5461 slots) master 1 additional replica(s) S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. #删除多余的slave从节点192.168.100.67 [root@Rocky_60 ~]#redis-cli -a 123456 --cluster del-node 192.168.100.60:6379 712b72558c88279da8f3b31253195b1cc4ba95f1 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Removing node 712b72558c88279da8f3b31253195b1cc4ba95f1 from cluster 192.168.100.60:6379 >>> Sending CLUSTER FORGET messages to the cluster... >>> Sending CLUSTER RESET SOFT to the deleted node. #删除集群文件 [root@Rocky_67 ~]#rm -f /apps/redis/data/nodes-6379.conf [root@Rocky_60 ~]#redis-cli -a 123456 --cluster check 192.168.100.60:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 3331 keys | 5462 slots | 1 slaves. 192.168.100.61:6379 (253d645d...) -> 3340 keys | 5461 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 3332 keys | 5461 slots | 1 slaves. [OK] 10003 keys in 3 masters. 0.61 keys per slot on average. >>> Performing Cluster Check (using node 192.168.100.60:6379) S: 9693d8397efde93bde348eed5ce976ddab342158 192.168.100.60:6379 slots: (0 slots) slave replicates 88c7caaa8381bd46cf840aca73462ce88ea095d6 M: e37c774a715b0336b0406c9c3bfd3c4035daac7e 192.168.100.62:6379 slots:[6826],[10923-16383] (5462 slots) master 1 additional replica(s) M: 253d645d4ddcfd9a8f3d97be5178606e182edfa1 192.168.100.61:6379 slots:[5461-6825],[6827-10922] (5461 slots) master 1 additional replica(s) S: ccaf26576134a5a9ed037bc520739e8e08f0b222 192.168.100.63:6379 slots: (0 slots) slave replicates e37c774a715b0336b0406c9c3bfd3c4035daac7e S: 5cec6a5761848fe9242c79721873c9b2f4df5dfc 192.168.100.65:6379 slots: (0 slots) slave replicates 253d645d4ddcfd9a8f3d97be5178606e182edfa1 M: 88c7caaa8381bd46cf840aca73462ce88ea095d6 192.168.100.64:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. [root@Rocky_60 ~]#redis-cli -a 123456 --cluster info 192.168.100.60:6379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 192.168.100.62:6379 (e37c774a...) -> 3331 keys | 5462 slots | 1 slaves. 192.168.100.61:6379 (253d645d...) -> 3340 keys | 5461 slots | 1 slaves. 192.168.100.64:6379 (88c7caaa...) -> 3332 keys | 5461 slots | 1 slaves. [OK] 10003 keys in 3 masters. 0.61 keys per slot on average. #查看集群信息 [root@Rocky_60 ~]#redis-cli -a 123456 -h 192.168.100.60 CLUSTER INFO Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 #只有6个节点 cluster_size:3 cluster_current_epoch:11 cluster_my_epoch:9 cluster_stats_messages_ping_sent:28127 cluster_stats_messages_pong_sent:27764 cluster_stats_messages_update_sent:4 cluster_stats_messages_sent:55895 cluster_stats_messages_ping_received:27764 cluster_stats_messages_pong_received:36319 cluster_stats_messages_update_received:7 cluster_stats_messages_received:64090
常见面试题
- Redis 做什么的,即在哪些场景下使用
- 如果监控 Redis 是否出现故障
- Redis客户端timeout报错突然增加,排查思路是怎样的?
- 请简单描述pipeline功能,为什么pipeline功能会提升redis性能?
- 本地redis-client访问远程Redis服务出错,说出几种常见的错误?
- key-value的大小超大或单key的qps超高,会对Redis本身造成什么样的影响、会对访问Redis的其
他客户端造成什么样的影响? - Zabbix 监控 Redis 哪些监控项
- RDB和AOF持久化区别
- docker拉取一个Redis如何实现数据持久化保存
- Redis 支持哪些数据类型
- Redis 如何实现消息队列
- 描述下常见的redis集群架构有哪些,他们之间的优缺点对比
- 主从复制工作原理
- Redis 如何实现高可用
- 哨兵工作原理
- Redis 集群的工作原理
- Redis 集群如果避免脑裂
- Redis 集群最少几个节点为什么?
- Redis的集群槽位多少个
- Redis集群中某个节点缺少一个槽位是否能使用
- Redis数据写入的时候是怎么在各个节点槽位分配数据的
- Redis的数据存储是以什么样的方式存储
- Redis集群的各槽位和总槽位之间什么关系
本文作者:天梯的脚印
本文链接:https://www.cnblogs.com/zxl1024320609/p/16746732.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步