Redis常见类型及常见命令
redis应用场景
- 缓存
- 计数器
- 排行榜
- 地理位置
- 队列
- 评论和弹幕
Redis6安装启动
- 源码编译安装
# 源码编译安装
wget https://download.redis.io/releases/redis-6.2.13.tar.gz
# 解压
tar zxvf redis-6.2.13.tar.gz
# 安装redis依赖
yum install gcc -y
# 进入解压包
cd redis-6.2.13/
# PREFIX指定软件安装的路径
make && make install PREFIX=/usr/local/redis6
# 创建其它目录文件
make /data/redis7001/{conf,data,log} -p
- 编辑配置文件
vim /data/redis7001/conf/redis.conf
# 内容
# 启动端口
port 7001
# yes后台运行
daemonize yes
# 指定redis进程pid文件路径
pidfile "/data/redis7001/data/redis.pid"
# redis日志的详细程度
loglevel notice
# 日志文件的路径和文件名
logfile "/data/redis7001/log/redis.log"
# 支持的数据库数量
databases 16
# redis的快照条件;1800秒以内只要有一次更改就执行一次快照保存(rdb落盘)
#save 1800 1
# rdb文件名称
dbfilename "dump.rdb"
# 持久性文件的目录
dir "/data/redis7001/data"
# 运行使用的最大内存量
maxmemory 1gb
# 当redis内存达到上限时所使用的淘汰策略
maxmemory-policy volatile-lru
# 是否开启aof持久化
appendonly no
# aof日志文件的名称
appendfilename "appendonly.aof"
# 慢查询时间的预值 单位 微秒
slowlog-log-slower-than 10000
# 慢查询日志的最大长度,最多记录多少条慢查询
slowlog-max-len 128
# redis的密码;生产环境建议设置密码
requirepass "IdfaUqTcdad82"
- 启动并登录redis
/usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
# 查看是否启动
ps -ef | grep redis
# 修改环境变量
vim /etc/profile
# 增加
export PATH="/usr/local/redis6/bin:$PATH"
source /etc/profile
redis-cli -v
# 登录redis
redis-cli -p 7001 -a IdfaUqTcdad82
- redis常用数据类型
数据类型 | 描述 |
---|---|
string | 字符串类型,一个key对应一个value |
hash | 键值对集合 |
list | 字符串列表,按插入顺序排队 |
set | string类型的无序集合,集合中元素是唯一的 |
zset | 有序集合,它类似于SET,但每个元素都会关联一个分数(score),分数用来对元素进行排序 |
HyperlogLog | 用于估计集合基数的数据类型 |
bitmap | 用户存储位数据,适用于布尔值和计数值 |
GEO | 存储地理位置数据,支持地理位置相关操作 |
常用数据类型的用法
- string
# 设置
set string_test aaa
# 获取
get string_test
# 删除
del string_test
# 计数
incr count_test
# 增加指定计数量
incrby count_test 3
# 减去
decr count_test
# 减去指定数量
decrby count_test 2
# 查询
get count_test
- hash
# 设置
hset user:01 name martin
hset user:01 age 18
# 获取
hget user:01 name
# 获取所有字段和值
hgetall user:01
# 获取hash表中字段数量
hlen user:01
# 获取hash表中所有字段
hkeys user:01
# 删除某个字段
hdel user:01 age
- list
# 插入列表头部
lpush list_test aaa
lpush list_test bbb
# 获取所有元素
lrange list_test 0 -1
# 插入到列表尾部
rpush list_test ccc
# 获取指定范围的元素
lrange list_test 0 0
# 查询前两个元素
lrange list_test 0 1
# 获取列表长度
llen list_test
# 移除并且获取列表的第一个元素
lpop list_test
# 移除并且获取列表的最后一个元素
rpop list_test
- set
# 添加元素
sadd set_test one
# 添加多个元素2
sadd set_test two three
# 返回集合中所有元素
smembers set_test
# 判断元素是否在集合中 返回1代表存在;0不存在
sismember set_test onne
# 删除集合中的元素
srem set_test two
- zset
# 添加元素
zadd zset_test 1 zhangshan
zadd zset_test 2 lishi
zadd zset_test 3 wangwu
# 查看元素
zrange zset_test 0 -1
# 查看元素和分数
zrange zset_test 0 -1 withscores
# 获取指定元素的分数
zscore zset_test "lishi"
# 从有序集合中移除元素
zrem zset_test "lishi"
# 获取有序集合元素个数
zcard zset_test
- HyperlogLog
# 添加元素
pfadd hll_test "apple" "banana" "cherry"
# 获取集合中元素数量
pfcount hll_test
- bitmaps
# 签到场景
# 第一天有签到记录
setbit user:1001 0 1
# 第二天有签到记录
setbit user:1001 1 1
# 第三天没有签到记录
setbit user:1001 2 0
setbit user:1001 4 1
# 查看某一天是否签到
getbit user:1001 1
getbit user:1001 2
# 统计签到数量
bitcount user:1001
- GEO
# 增加地理位置
geoadd geo_test 20 30 "a"
geoadd geo_test 40 60 "b"
# 求a和b之前的距离 单位km
geodist geo_test "a" "b" km
# 查询指定范围的地点 经度 25 纬度 35 范围1000km以内的地点
georadius geo_test 25 35 1000 km
redis常用管理命令
- 在redis中认证
redis-cli -p 7001 -a IdfaUqTcdad82
或者
redis-cli -p 7001
auth IdfaUqTcdad82
- 查看服务器的各种信息
info
# 查看某一块的信息
info CPU
- 查看所有的key
keys *
- 查看某个前缀的key
keys name*
- 找到某个前缀的key并删除
# 查找以name开头的key。--scan 扫描,--pattern 模式匹配
redis-cli -p 7001 -a IdfaUqTcdad82 --scan --pattern "name*"
# 并且删除,xargs 代表对前面的结果进行处理,-L 5000 每次处理5000条数据
redis-cli -p 7001 -a IdfaUqTcdad82 --scan --pattern "name*" | xargs -L 5000 redis-cli -p 7001 -a IdfaUqTcdad82 del
- 重命名key
set hehe 1111
# 改名,重复会覆盖
rename hehe hehe_bak
get hehe_bak
或者
set one 111
# renamenx 新名字必须是之前不存在的
renamenx one two
- 判断key是否存在
# 返回 1 存在,0不存在
exists hehe
- 查看key类型
type hehe_bak
- 查看key大小
# 单位字节
memory usage hehe_bak
- 查看key的内部信息
debug object hehe_bak
# key存放的内存地址:引用计数:键的编码方式:key的序列化长度:key的lru值,最近最少使用的值:键自从上一次访问的空闲时间
- 设置key的过期时间
set martin 111
# 300秒过期
expire martin 300
# 查看过期时间
ttl martin
# 移除key的过期时间
persist martin
- 发布订阅
# 第一个窗口
SUBSCRIBE chat
# 第二个窗口
PUBLISH chat "hello redis"
# 第一个窗口就会收到对应的消息
- 切换数据库
# 默认在0数据库,切换到2
select 2
set aaa 111
info keyspace
- 返回当前库key的数量
dbsize
- 清空当前数据库的所有key
flushdb
- 清空redis
flushall
- 查看和修改配置
# 查看所有配置
config get *
# 查看最大内存
config get maxmemory
# 查看包含关键字的配置
config get *memory*
# 修改配置
config set maxmemory 2G
# 将修改的配置持久化到配置文件
config rewrite
# 查看配置文件
vim /data/redis7001/conf/redis.conf
- 获取慢查询日志
# 获取5条
slowlog get 5
# 查看与慢查询有关的参数
config get slow*
# slowlog-max-len 最多记录多少条慢查询记录;slowlog-log-slower-than 超过这个时间就会记录到慢查询,单位微秒
- 查看客户端连接
client list
- 杀掉某个连接
client kill 192.168.12.162:50732
- 命令行直接执行命令
redis-cli -p 7001 -a IdfaUqTcdad82 info
redis-cli -p 7001 -a IdfaUqTcdad82 client list
- 让redis服务崩溃
debug segfault
ps -ef | grep 7001
# 启动
/usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
- 关闭redis服务器
# 在redis命令里执行,建议此方式关闭redis
shutdown
详解Redis RDB
把内存中的数据存储到磁盘中,当redis重启会读取RDB文件恢复数据
几种RDB持久化场景
- 手动执行RDB持久化
# 这个命令会在主线程执行,会导致阻塞,线上环境禁止使用
save
# 启用子进程来持久化,避免主线程阻塞
bgsave
# 查看数据目录
config get dir
# 确定bgsave是否正确执行,查看RDB相关参数
info persistence
loading:0 ;当前是否在进行RDB文件的加载操作
current_cow_size:0 ;写时复制技术占用的内存
current_cow_size_age:0 ;上一次current_cow_size的时间,单位秒
current_fork_perc:0.00 ;当前fork进程的进度百分比
current_save_keys_processed:0 ;当前RDB操作已处理keys的数量
current_save_keys_total:0 ;当前RDB持久化进程一共需要处理的键数量
rdb_changes_since_last_save:0 ;从上一次执行RDB以来更改的数量
rdb_bgsave_in_progress:0 ;是否有RDB持久化的后台进程正在进行,0表示RDB已经操作完成
rdb_last_save_time:1694702221 ;上次执行RDB持久化的时间戳
rdb_last_bgsave_status:ok ;上次执行RDB持久化的执行状态
rdb_last_bgsave_time_sec:0 ;上一次执行RDB持久化所花费的时间
rdb_current_bgsave_time_sec:-1 ;当前正在执行的RDB持久化操作花费的时间
rdb_last_cow_size:409600 ;上一次RDB持久化操作中使用的写时复制技术的内存大小
aof_enabled:0 ;
aof_rewrite_in_progress:0 ;
aof_rewrite_scheduled:0 ;
aof_last_rewrite_time_sec:-1 ;
aof_current_rewrite_time_sec:-1 ;
aof_last_bgrewrite_status:ok ;
aof_last_write_status:ok ;
aof_last_cow_size:0 ;
module_fork_in_progress:0 ;
module_fork_last_cow_size:0 ;
- 配置自动执行RDB持久化
# 查看配置文件
vim /data/redis7001/conf/redis.conf
# 启动端口
port 7001
# yes后台运行
daemonize yes
# 指定redis进程pid文件路径
pidfile "/data/redis7001/data/redis.pid"
# redis日志的详细程度
loglevel notice
# 日志文件的路径和文件名
logfile "/data/redis7001/log/redis.log"
# 支持的数据库数量
databases 16
# redis的快照条件;1800秒以内只要有一次更改就执行一次快照保存(rdb落盘)
#⚠️save 1800 1 新增下列三行参数
save 900 1
save 300 10
save 60 10000
# rdb文件名称
dbfilename "dump.rdb"
# 持久性文件的目录
dir "/data/redis7001/data"
# 运行使用的最大内存量
maxmemory 1gb
# 当redis内存达到上限时所使用的淘汰策略
maxmemory-policy volatile-lru
# 是否开启aof持久化
appendonly no
# aof日志文件的名称
appendfilename "appendonly.aof"
# 慢查询时间的预值 单位 微秒
slowlog-log-slower-than 10000
# 慢查询日志的最大长度,最多记录多少条慢查询
slowlog-max-len 128
# redis的密码;生产环境建议设置密码
requirepass "IdfaUqTcdad82"
# 重启 或者在redis命令行执行
config set save "900 1"
- 其他触发RDB持久化的场景
在新建redis主从复制的时候,主节点会执行一次bgsave保存RDB文件到本地,然后再发送给从节点;
在执行shutdown的时候,如果没有开启aof就会自动执行bgsave将内存中的数据进行落盘,保证在启动的时候数据不会丢失。
RDB扩展
- 备份恢复测试
- RDB压缩
# 查看配置参数 默认开启,建议开启
config get rdbcompression
- 临时修改RDB路径
# 创建目录
mkdir /data/redis7001/tem_data
# 修改路径
config get dir
config set dir /data/redis7001/tem_data/
# 测试
bgsave
RDB注意事项
- bgsave对redis也是有影响的
建议在从库落盘 - 单机多实例的RDB备份尽量错开
- RDB持久化并不能保证所有数据落盘
详解Redis AOF
AOF介绍
- 什么是AOF?
它会记录Redis收到的每一条写命令,如果Redis发生了崩溃,重启之后就会更具日志文件的内容将写操作重头到尾执行一次,以完成数据的恢复。
- 开启AOF日志
vim /data/redis7001/conf/redis.conf
# 修改参数
appendonly yes
# 启动
# 查看配置
config get appendonly
# 动态修改
config set appendonly yes
- AOF的内容
# 默认在数据目录
AOF相关配置
- AOF持久化选项
config get appendfsync
everysec :表示每秒写回,每个写命令执行完,只是先把日志写到AOF的内存缓存区,每隔一秒把缓冲区中的内容写到磁盘
always :表示同步写回,每个写命令执行完立马同步到磁盘
no :表示操作系统控制写回,每个写命令执行完只是先把日志写到AOF的内存缓存区,由操作系统决定何时将缓存区的内容写回到磁盘
配置建议: 对性能要求很高并且对数据可靠性要求不高 no;高可靠性保证always;允许数据有一点丢失,性能不受太大影响 everysec。
- AOF重写机制
如果实例运行比较久并且修改比较频繁那么Redis的AOF文件可能会比较大,通过AOF重写机制解决。会把AOF的内容重写只保留可以恢复数据的最小指令集。
AOF文件为什么可以变小?
- 旧日志文件中的多条命令再重写后新日志中就变成了一条命令
- 已经过期的key就不再写入新的AOF文件中
# 手动触发一次AOF重写
bgrewriteaof
# 配置参数让AOF自动触发重写,超过一次这个大小就会触发一次AOF重写
config get "auto-aof-rewrite-min-size"
# 当前AOF文件空间超过上一次重写后AOF文件空间的多少百分比就会触发重写
config get "auto-aof-rewrite-percentage"
- AOF相关状态参数
info persistence
loading:0 ;当前是否在进行RDB文件的加载操作
current_cow_size:0 ;写时复制技术占用的内存
current_cow_size_age:0 ;上一次current_cow_size的时间,单位秒
current_fork_perc:0.00 ;当前fork进程的进度百分比
current_save_keys_processed:0 ;当前RDB操作已处理keys的数量
current_save_keys_total:0 ;当前RDB持久化进程一共需要处理的键数量
rdb_changes_since_last_save:0 ;从上一次执行RDB以来更改的数量
rdb_bgsave_in_progress:0 ;是否有RDB持久化的后台进程正在进行,0表示RDB已经操作完成
rdb_last_save_time:1694702221 ;上次执行RDB持久化的时间戳
rdb_last_bgsave_status:ok ;上次执行RDB持久化的执行状态
rdb_last_bgsave_time_sec:0 ;上一次执行RDB持久化所花费的时间
rdb_current_bgsave_time_sec:-1 ;当前正在执行的RDB持久化操作花费的时间
rdb_last_cow_size:409600 ;上一次RDB持久化操作中使用的写时复制技术的内存大小
aof_enabled:0 ;AOF是否开启
aof_rewrite_in_progress:0 ;是否有AOF重写操作正在进行
aof_rewrite_scheduled:0 ;是否有AOF重写操作已经被调度
aof_last_rewrite_time_sec:-1 ;上一次AOF重写操作的执行时间
aof_current_rewrite_time_sec:-1 ;当前正在执行的AOF重写操作花费的时间
aof_last_bgrewrite_status:ok ;上一次AOF重写操作的执行状态
aof_last_write_status:ok ;上一次AOF写入操作的执行状态
aof_last_cow_size:0 ;上一次AOF操作中使用的cow机制内存大小,cow=copy on write 写时复制技术
module_fork_in_progress:0 ;
module_fork_last_cow_size:0 ;
aof_current_size:127 ;AOF当前大小
aof_base_size:127 ;AOF基础大小
aof_pending_rewrite:0 ;等待执行AOF重写的数量
aof_buffer_length:0 ;AOF缓冲区的大小
aof_rewrite_buffer_length:0 ;AOF重写缓冲区的大小
aof_pending_bio_fsync:0 ;等待执行AOF fsync操作的数量
aof_delayed_fsync:0 ;延迟执行AOF fsync操作的数量
- 重启通过AOF恢复数据
- 写入数据
- 关闭Redis并删除RDB文件
shutdown
ps -ef | grep redis
cd /data/redis7001/data/
rm -rf dump.rdb
- 再启动Redis并确定数据
- AOF异常恢复实验
- 构造AOF异常场景
修改AOF文件 - 重启尝试
shutdown
# 再重启,无法正常启动
# 去查看日志
cd /data/redis7001/log/
tail -f redis.log
- 修复AOF文件
redis-check-aof --fix ../data/appendonly.aof
# 再启动redis
Redis 7.0 AOF变化
- 安装Redis7.0
- 7.0配置AOF单独目录
- 7.0的3个AOF文件
# 控制AOF文件夹的名字
config get appenddirname
# 开启AOF
config set appendonly yes
# 进入数据目录,有个默认的文件夹 appendonlydir
cd /data/redis7201/data/
cd appendonlydir
ls
.base.rdb ;基础的AOF,一个
.incr.aof ;增量AOF,可以有多个
.aof.manifest ;AOF的清单文件
AOF的一些相关问题
- Redis采用AOF而不是WAL的原因
WAL :很多数据库都是采用WAL,先把修改的数据记录到日志中再进行写数据的提交,可以方便通过日志进行数据恢复
AOF :先执行写命令,再把数据写入到内存中再写日志文件;可以避免错误命令的情况,AOF是在命令执行后再记录日志所以不会堵塞当前的写操作
- AOF和RDB都开启,重启使用什么来恢复数据?
Redis会使用AOF来恢复数据,AOF数据更完整。 - AOF的优势和劣势
优势:丢数据的概率低,且可读性强
劣势:比RDB更占空间,因为记录的是每一条写命令,且AOF恢复数据恢复速度慢很多,每一次读写都落盘性能也会有点问题。
建议:只做缓存建议都不开启,当数据库用需要备份,可以在从库开启AOF和RDB落盘
Redis主从复制
准备复制环境
- 配置Redis主从复制
# 在从库
# 配置主库的密码
config set masterauth IdfaUqTcdad82
# 建立关系,配置主库的ip和端口
replicaof 192.168.12.161 7001
# 主从关系配置持久化
vim /data/redis7001/conf/redis.conf
# 新增参数
masterauth "IdfaUqTcdad82"
replicaof 192.168.12.161 7001
- 查看复制信息
# 在从库redis
info replication
- 确定数据同步
Redis复制原理
Redis复制原理.jpg复制相关维护
- 判断主从延迟
# 在主节点执行
info replication
slave0:ip=192.168.12.162,port=7001,state=online,offset=77035,lag=1
offset 表示从库的偏移量
master_repl_offset:77035 主库的偏移量,两个一样代表没有延迟
- 网络闪断导致全量复制
config get repl-backlog-size
- 断开复制关系
# 在从库redis,情况主节点信息;断开后不会清除已经复制的数据
replicaof no one
复制架构调整
- 更换主节点
# 建立复制关系
config set masterauth IdfaUqTcdad82
replicaof 192.168.12.161 7001
info replication
# 切换主节点,切换主节点会删除已经复制的数据然后复制新主节点的数据
replicaof 192.168.12.163 7001
- 级联复制配置
# 161->162->163
#在 162执行
replicaof no one
config set masterauth IdfaUqTcdad82
replicaof 192.168.12.161 7001
# 在 163执行
replicaof no one
config set masterauth IdfaUqTcdad82
replicaof 192.168.12.162 7001
# 查看复制状态
info replication
# 如果需要配置持久化
config rewrite
- 复制相关建议
- 建议在低峰时进行新的主从配置
- 建议一个主节点别挂载太多的从节点
- 建议一台物理机上运行尽可能少的主节点
Redis主从之哨兵
哨兵的工作流程
Redis哨兵的工作流程.jpg哨兵的选主逻辑
- 首先:优先级靠前的
# 参数越小优先级越高
config get replica-priority
- 其次:便宜量最大的
info replication
# salve_repl_offset 越大同步越靠前
- 再次:ID最小的
部署哨兵集群
- 配置一主两从架构
# 清空两台从库配置关系
replicaof no one
# 每个实例修改
config set masterauth IdfaUqTcdad82
# 在两个从库执行
replicaof 192.168.12.161 7001
# 在主库查看信息
info replication
- 配置哨兵文件
# 在每个Redis实例 创建哨兵文件夹(3个)
mkdir /data/sentinel26379/{data,conf,log} -p
# 在每个节点增加配置文件(3个)
vim /data/sentinel26379/conf/sentinel.conf
# 哨兵端口
port 26379
# 后台运行
daemonize yes
# 日志文件
logfile "/data/sentinel26379/log/26379.log"
# 数据目录
dir /data/sentinel26379/data/
# sentinel监控的Redis,监控的集群名是mymaster,主的ip和端口,2表示至少有两个哨兵同意就进行故障切
sentinel monitor mymaster 192.16812.161 7001 2
# 被监控Redis的密码
sentinel auth-pass mymaster IdfaUgTcdad82
# 判断Reids 主观下线的阈值,单位毫秒
sentinel down-after-milliseconds mymaster 10000
- 启动哨兵
# 在每个实例启动
redis-sentinel /data/sentinel26379/conf/sentinel.conf
# 查看是否启动
ps -ef|grep sentinel
# 哨兵启动后会在配置文件自动新增一些参数
哨兵常用命令
- 显示其他哨兵的状态
# 登录哨兵
redis-cli -p 26379
# 显示其他哨兵的状态
sentinel sentinels mymaster
- 显示要监控的集群状态
sentinel masters
# 查看某一个master的状态
sentinel master mymaster
# 查看某一个master的地址
sentinel get-master-addr-by-name mymaster
# 查看被监控主的从库状态
sentinel replicas mymaster
- 强制进行故障转移
sentinel failover mymaster
# 查看
sentinel get-master-addr-by-name mymaster
# 在去新的主查看
info replication
Go程序通过哨兵操作Redis
- 通过chatgpt编写操作Redis的程序
编写一个Go程序,能连接Redis的哨兵,有3个哨兵实例19216812161:26379,19216812162:26379,19216812163:26379,Redis密码是xxx
帮忙每秒往Redis里面写一个唯一的key
写入成功,输出success;
写入失败,输出错误,但是循环继续
- 修改代码(redis密码)
- 测试代码
故障切换测试
- 关闭住主实例并查看程序输出
# 关闭主
info replication
shutdown
- 分析故障恢复过程的哨兵日志
# 查看日志文件
tail -n 30 /data/sentinel26379/log/26379.log
- 确定新的复制架构
# 在新主查看信息
info replication
# 再启动关闭的实力
redis-sentinel /data/sentinel26379/conf/sentinel.conf
# 再查看信息
info replication
关于哨兵的建议
- 至少需要3个sentinel实例才能实现稳健的部署
- sentinel放在不同的机柜上
- 需要保证客户端支持sentinel
Redis Cluster架构
Redis Cluster架构.jpgRedis Cluster部署
需要部署六台redis
- 让chatgpt编写Redis部署脚本
⚠️... ...
在每台实例运行部署脚本(三台服务器,每台安装2个redis)
# 与常规安装redis相比新增集群参数
# 开启集群
cluster-enabled yes
cluster-config0file /data/redis8001/data/nodes8001.conf
# 节点的超时事件,毫秒
cluster-node-timeout 5000
# 需要密码的话
masterauth "IdfaUqTcdad82"
- 创建集群
# 随便一台机器执行; --cluster 表示加集群的参数;create 创建集群;后面跟集群节点;--cluster-replicas 表示每个节点分配几个从节点;-a 表示密码(生产环境也是建议每个节点分配一个从节点)
redis-cli --cluster create 192.168.12.161:8001 192.168.12.161:8002 192.168.12.162:8001 192.168.12.162:8002 192.168.12.163:8001 192.168.12.163:8002 --cluster-replicas 1 -a IdfaUqTcdad82
# 查看集群的状态
redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
# 查看集群配置文件(启动集群后redis自动创建)
cat /data/redis8001/data/node8001.conf
集群使用
- 数据测试
# Redis Cluster 可以通过任意一个节点redis连接集群;-c 表示按集群的方式连接redis
redis-cli -p 8001 -a IdfaUqTcdad82 -c
# 查看集群信息,在redis内执行
cluster nodes
- 集群相关命令
# 查看某个key在哪个槽上
cluster keyslot aaa
# 查看某个槽有多少个key,只能查询本节点槽的数量
cluster countkeysinslot 10439
# 返回某个槽的某些key;10 查询槽中10个key
cluster getkeysinslot 13785 10
通过Go程序连接Redis Cluster
- 通过chatgpt编写Go连接Redis Cluster的代码
编写Go程序,需要连接带密码的Redis Cluster
每秒写入一个唯一的key
写入成功和失败都输出带时间的日志
- 修改代码
- 运行代码
故障恢复测试
- 关闭一个主实例
# 登录redis后执行
shutdown
- 查看集群状态
cluster nodes
- 启动关掉的实例
# 新启动的实例会变成从节点
/usr/local/redis6/bin/redise-serrver /data/redis8001/conf/redis.conf
# 极端场景,主和从都挂掉,是否继续提供服务参数;yes 表示主和从不可用的时候整个集群就不可用;no 这个主从节点不可用,其他节点可用,但是挂的节点的数据不可查询
config get cluster-require-full-coverage
Redis Cluster扩容
- 部署要扩容的Redis实例
# 在两台实例上各部署一个Redis
- 添加新的主从实例到集群
# 192.168.12.161:8003 新增的节点;192.168.12.161:8001 已经存在的任一节点
redis-cli --cluster add-node 192.168.12.161:8003 192.168.12.161:8001 -a IdfaUqTcdad82
# 查看集群状态
redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
# 为新增的主实例添加从实例;192.168.12.162:8003 新增的节点;192.168.12.161:8001 已经存在的任一节点;--cluster-slave 以从节点加入;--cluster-master-id 主节点的id
redis-cli --cluster add-node 192.168.12.162:8003 192.168.12.161:8001 --cluster-slave --cluster-master-id 70502ee36d2476e6f39d335d56373d141daa4653 -a IdfaUqTcdad82
# 查看集群状态;此时新加的主从节点还没有槽
redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
- 进行槽迁移
# 192.168.12.161:8001 集群任一节点;reshard 重新分配槽;槽总数/主从个数=新增节点的槽
redis-cli --cluster reshard 192.168.12.161:8001 -a IdfaUqTcdad82
Redis Cluster缩容
- 转移要缩容节点的槽
# --cluster-from 表示要迁移槽的源节点;...a4777 要迁移到哪个节点;--cluster-slots 要迁移槽的数量;192.168.12.161:8001 集群任意一节点的ip和端口
redis-cli --cluster reshard --cluster-from 70502ee36d2476e6f39d335d56373d141daa4653 --cluster-to 70502ee36d2476e6f39d335d56373d141daa4777 --cluster-slots 1365 192.168.12.161:8001 -a IdfaUqTcdad82
# 迁移时最好迁移到连续编号的槽节点
- 删除要缩容的节点
# 192.168.12.161:8001 集群任意一节点的ip和端口;...a4653 要删除的节点
redis-cli --cluster del-node 192.168.12.161:8001 70502ee36d2476e6f39d335d56373d141daa4653 -a IdfaUqTcdad82
redis-cli --cluster del-node 192.168.12.161:8001 70502ee36d2476e6f39d335d56373d141daa4666 -a IdfaUqTcdad82
# 查看集群状态
redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
Redis Cluster原理解析
- 虚拟槽和哈希标签
Redis Cluster采用虚拟槽分区,一个集群有16384个虚拟槽,虚拟槽类似数据分区,每个键值对都会根据它的key再按照CRC16算法计算一个16bit的值,然后这个16bit的值对16384进行取模,通过模来映射到槽中。
# 有时候想要某些key在一个槽里面,可以用哈希标签
redis-cli -p 8001 -a IdfaUqTcdad82 -c
set {user001}.name aaa
set {user001}.email aaa@qq.com
# 查看在哪个槽
cluster keyslot {user001}.name
# 查看这个槽下所有key
cluster getkeysinslot 1390 10
# 不能过度使用,可能会导致数据分表不均匀
- 客户端怎样定位数据的?
在客户端和集群建立连接后,实例就会把hash槽的分片信息发送给客户端,每个实例会把自己的hash槽信息发送给集群内其它实例,这样每个实例都会知道所有hash槽和实例的对应关系。
- 故障转移
集群内每个节点都会定期向集群中其它节点发送ping命令,互相探测,这样可以交换节点状态信息。
# 选取资格判断参数
config get cluster-node-timeout
# 如果这个参数设置为0,那么不管断开多久多会参与选举
config get cluster-slave-validity-factor
Redis Cluster的优势
- 无中心架构
- 动态扩缩容
- 高可用性
Redis Cluster的限制
- key批量操作支持有限
- 不能将一个大的键值对象映射到不同的节点
- 只支持单个库
网友评论