ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

redis学习笔记-2

2022-01-25 18:03:41  阅读:179  来源: 互联网

标签:6379 redis 笔记 学习 cluster 6380 172.16 节点


视频实操总结

redis安装部署

环境准备
1、准备三台机器,修改主机名,配置hosts文件,设置互信
hostnamectl set-hostname db03
cat >/etc/hosts <<EOF
172.16.190.129 db01
172.16.190.128 db02
172.16.190.130 db03
EOF
#ssh-keygen
[root@db02 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@db02 #ansible认证需要自己信任自己
目录规划
/data/soft #软件下载路径
/opt/redis_cluster/redis_{PORT}/{conf,logs,pid}  #redis安装路径
/data/redis_cluster/redis_{PORT}/redis_{PORT}.rdb #redis数据目录
/root/scripts/redis_shell.sh     #运维脚本
安装步骤
mkdir /data/soft -p
mkdir /opt/redis_cluster/redis  -p
mkdir /opt/redis_cluster/redis_6379/{conf,logs,pid} -p
mkdir /data/redis_cluster/redis_6379 -p
wget http://download.redis.io/releases/redis-6.2.6.tar.gz -P /data/soft/ #-P 指定下载位置
tar -zxf /data/soft/redis-6.2.6.tar.gz -C /opt/redis_cluster/
ln -s /opt/redis_cluster/redis-6.2.6/ /opt/redis_cluster/redis #建立软连接方便后期升级
make  #编译
make install #编译安装,将编译文件可执行命令复制到$PATH环境变量目录下,使命令可执行

 

配置文件说明
### 配置文件放在了安装目录
cat > /opt/redis_cluster/redis_6379/conf/redis_6379.conf <<EOF  
### 以守护进程模式启动
daemonize yes
### 绑定的主机地址
bind $(hostname -i)  
### 监听端口
port 6379
### pid 文件和 log 文件的保存地址
pidfile /opt/redis_cluster/redis_6379/pid/redis_6379.pid
logfile /opt/redis_cluster/redis_6379/logs/redis_6379.log
### 设置数据库的数量,默认数据库为 0
databases 16
### 指定本地持久化文件的文件名,默认是 dump.rdb
dbfilename redis_6379.rdb
### 本地数据库的目录
dir /data/redis_cluster/redis_6379
EOF
redis启停
#redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
#redis-cli -h db01 shutdown
错误锦集
6652:C 18 Jan 2022 11:21:41.615 # Can't chdir to '/data/redis_cluster/redis_6379': No such file or directory
#缺少数据目录,新建即可
6659:M 18 Jan 2022 11:22:45.613 * monotonic clock: POSIX clock_gettime
6659:M 18 Jan 2022 11:22:45.617 # Warning: Could not create server TCP listening socket ###:6379: Name or service not known
6659:M 18 Jan 2022 11:22:45.617 # Failed listening on port 6379 (TCP), aborting.

# 检查配置文件发现配置文件串行

redis字符类型

redis string
127.0.0.1:6379> set k2 100
OK
127.0.0.1:6379> incr k2 #INCR命令将字符串值解析成整型,默认加1并保存为新字符串
(integer) 101
127.0.0.1:6379> incrby k2 100  #解析成整型 加的值在后面
(integer) 201
127.0.0.1:6379> get k2
"201"
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3  #一次存储多个值
OK
127.0.0.1:6379> mget k1 k2 k3    #一次获取多个值
1) "v1"
2) "v2"
3) "v3
127.0.0.1:6379> EXISTS k1  #检查键值是否存在
(integer) 1
127.0.0.1:6379> del k1   #删除键值
(integer) 1
127.0.0.1:6379> EXISTS k1
(integer) 0
127.0.0.1:6379> type k2  #返回键值存储类型
string
127.0.0.1:6379> ttl k2   #检测键值过期时间,-1 永不过期 -2键值已删除
(integer) -1
127.0.0.1:6379> EXPIRE k2 10  #设置键值过期时长为10s
(integer) 1
127.0.0.1:6379> ttl k2
(integer) 6
127.0.0.1:6379> ttl k2
(integer) -2
127.0.0.1:6379> get k2
(nil)
redis 列表
127.0.0.1:6379> RPUSH k6 A #RPUSH 命令可向 list 的右边(尾部)添加一个新元素 
(integer) 1
127.0.0.1:6379> LPUSH k6 b #LPUSH 命令可向 list 的左边(头部)添加一个新元素
(integer) 2
127.0.0.1:6379> LRANGE k6 0 -1
1) "b"
2) "A"
127.0.0.1:6379> LRANGE k6 0 1 #LRANGE 可以从 list 中取出一定范围的元素
1) "b"
2) "A

127.0.0.1:6379> LRANGE k6 0 5  ##完整列表
1) "d"
2) "c"
3) "b"
4) "A"
127.0.0.1:6379> rpop k6 1 #从右边删除一个元素
1) "A"
127.0.0.1:6379> lpop k6 1 #从左边边删除一个元素
1) "d"
127.0.0.1:6379> LRANGE k6 0 5 ##完整列表
1) "c"
2) "b"
redis 哈希(hash)
127.0.0.1:6379> hmset test:1999 name wtl  age 28 job daye  #HMSET 指令设置 hash 中的多个域
OK
127.0.0.1:6379> hget test:1999 name #hget获取单个域
"wtl"
127.0.0.1:6379> hmget test:1999 name age job #hmget 取回一系列值
1) "wtl"
2) "28"
3) "daye"
127.0.0.1:6379> hget test:1999 age;  #hget只能取到第一个值 其他值获取不到
(nil)
127.0.0.1:6379> HMSET test:1999 qq 1116  #可以继续插入写的列(hash不一定需要指定冒号和数字)
OK
127.0.0.1:6379> HGETALL test:1999 #HGETALL获取域内所有值
1) "name"
2) "wtl"
3) "age"
4) "28"
5) "job"
6) "daye"
7) "qq"
8) "1116"
redis集合
127.0.0.1:6379> sadd set 123 321  #SADD 指令把新的元素添加到 set 中
(integer) 1
127.0.0.1:6379> SMEMBERS set  #获取值
1) "123"
2) "321"
127.0.0.1:6379> sadd k7 123 321 222 333 123  ##set集合不能出现重复数据,出现的重复数据不会被插入
(integer) 4
127.0.0.1:6379> SMEMBERS k7   #无序插入
1) "123"
2) "222"
3) "321"
4) "333"
127.0.0.1:6379> SREM k7 123 #删除集合的指定值
(integer) 1
127.0.0.1:6379> SMEMBERS k7
1) "222"
2) "321"
3) "333"
127.0.0.1:6379> sadd k11 1 2 3 4
(integer) 4
127.0.0.1:6379> sadd k12 1  5
(integer) 2
127.0.0.1:6379> SDIFF k11 k12  #差集
1) "2"
2) "3"
3) "4"
127.0.0.1:6379> SINTER k11 k12 #交集
1) "1"
127.0.0.1:6379> SUNION k11 k12 #并集
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"

redis 持久化

优缺点
redis持久化分为rdb和aof方式;
rdb:基于快照的持久化,速度更快,一般用作备份,主从复制也是依赖于 rdb 持久化功能
aof:以追加的方式记录 redis 操作日志的文件。可以最大程度的保证 redis 数据安全,类似于 mysql 的 binlog
核心配置
#rdb
dir /data/redis_cluster/redis_6379
dbfilename redis_6379.rdb
save 900 1 #900 秒(15 分钟)内有 1 个更改
save 300 10 #300 秒(5 分钟)内有 10 个更改
save 60 10000 #60 秒内有 10000 个更改
#AOF
appendonly yes #是否打开 aof 日志功能
appendfsync always #每 1 个命令,都立即同步到 aof
appendfsync everysec #每秒写 1 次
appendfsync no #写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到 aof.
实施过程
###rdb
1、cp redis_6379.conf{,bak} #备份配置文件
2、配置文件新增rdb配置
3、插入1000条数据,观察rdb文件变化
for i in {1..1000};  do redis-cli set k_${i} v_${i}; echo "${i} is ok"; done
100 changes in 300 seconds. Saving...  #100-300秒 开始保存
Background saving started by pid 1927 #备份pid建立
DB saved on disk #数据保存到磁盘上
RDB: 4 MB of memory used by copy-on-write #RDB:通过复制写入的4 MB内存
Background saving terminated with success  #保存背景终止了成功
从命令执行到文件保存到磁盘经过了大概5分钟
###可以通过修改参数缩短内存写入磁盘时间

###AOF
1、取消rdb相关配置,修改为aof相关配置
2、数据持续写入 观察aof文件变化

redis安全认证

保护模式
protected-mode  yes/no (保护模式,是否只允许本地访问)
127.0.0.1:6379> CONFIG GET protected-mode
1) "protected-mode"
2) "yes"
bind 指定ip地址监听
127.0.0.1:6379> CONFIG GET bind
1) "bind"
2) "127.0.0.1 172.16.190.129" 如果本地使用则只配置127
requirepass {password}
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> get k1111  ## 没有密码认证不能执行命令
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get k1111
(nil)
取消密码认证
#配置文件中注释相关行即可

主从复制

主从介绍

在分布式系统中解决单点问题,通常把数据复制多个副本到其他机器,满足故障恢复和负载均衡等要求;

复制功能是高可用的redis基础,哨兵和集群都是复制的基础上实现高可用的。

实施过程
1、创建对应目录将单节点编译文件拷贝到从节点
mkdir /opt/redis_cluster/redis_6379/{conf,logs,pid} -p
mkdir /data/redis_cluster/redis_6379 -p
mkdir /opt/redis_cluster/redis -p
scp -r /opt/redis_cluster/redis/* db03:/opt/redis_cluster/redis
make install
2、增加防火墙策略
firewall-cmd --add-port=6379/tcp --permanent
firewall-cmd --reload
3、修改配置文件
cat > /opt/redis_cluster/redis_6379/conf/redis_6379.conf <<EOF  
### 以守护进程模式启动
daemonize yes
### 绑定的主机地址
bind $(hostname -i)  
### 监听端口
port 6379
### pid 文件和 log 文件的保存地址
pidfile /opt/redis_cluster/redis_6379/pid/redis_6379.pid
logfile /opt/redis_cluster/redis_6379/logs/redis_6379.log
### 设置数据库的数量,默认数据库为 0
databases 16
### 指定本地持久化文件的文件名,默认是 dump.rdb
dbfilename redis_6379.rdb
### 本地数据库的目录
dir /data/redis_cluster/redis_6379
EOF
4、确认redis各节点服务启动,验证单节点是否可用
5、从节点输入SLAVEOF db01 6379 即可复制主节点的数据
#info replication 查看主从复制状态
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:db01
master_port:6379
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
slave_read_repl_offset:10359
slave_repl_offset:10359
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:018cf29ebea94cdb190f45111ca60c929ac9e030
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:10359
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:43
repl_backlog_histlen:10317
6、主节点插入数据从节点读取验证
redis主从故障恢复
1、主备验证完成后关闭主节点进程,模仿故障发生(先备份rdb数据)
[root@db01 redis_6379]# redis-cli
127.0.0.1:6379> bgsave
Background saving started
2、关闭进程后查看复制状态信息
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:db01
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
3、手动关闭主从复制
db03:6379> SLAVEOF no one
OK
4、再次备份从节点数据并在剩余的节点中找出主节点,将从节点提升为主节点
db02:6379> SLAVEOF db03 6379
OK
5、插入数据模拟业务恢复,并验证从节点数据是否复制过去
for i in {1..1000};  do redis-cli -h db03 set w_${i} v_${i}; echo "${i} is ok"; done
6、启动db01进程,并加入从节点复制数据
db01:6379> SLAVEOF db03 6379
db01:6379> get w_1101    #最新数据验证获取成功
"v_1101"
7、关闭db02、db01、db03复制,恢复到单机版本,在db02和db03节点执行命令将db01 设置为主
db01:6379> SLAVEOF no one
OK
db02:6379> SLAVEOF db01 6379
OK
db01:6379> info replication
# Replication
role:master  --显示db01为主,有两个从节点
connected_slaves:2
slave0:ip=172.16.190.128,port=6379,state=online,offset=56315,lag=0
slave1:ip=172.16.190.130,port=6379,state=online,offset=56315,lag=1
master_failover_state:no-failover
master_replid:07d47c052ae0fed9ef1bfd64f925b5b603950b14
master_replid2:f0cf44ff24ce12b3b559d1d91b0fcc1587a45b21
master_repl_offset:56315
second_repl_offset:56288
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:48473
repl_backlog_histlen:7843
断开复制主要流程:
1.断开与主节点复制关系
2.从节点晋升为主节点
从节点断开复制后不会抛弃原有数据,只是无法再获取主节点上的数据变化.
通过 slaveof 命令还可以实现切主操作,所谓切主是指把当前从节点对主节点的复制切换到另一个主节点. 执行 slaveof {newMasterIp} {newMasterPort}命令即可.
切主操作流程如下:
1.断开与旧主节点的复制关系
2.与新主节点建立复制关系
3.删除从节点当前所有数据
4.对新主节点进行复制操作
提示: 线上操作一定要小心,因为切主后会清空之前所有的数据.

哨兵(Sentinel)

哨兵介绍

redis的主从模式下,主节点出现故障不能提供服务,需要人工干预,将从节点晋升为主节点,还需要修改客户端的配置(连接ip等),哨兵主要解决redis主从需要人工干预的问题。

###哨兵的缺点
1、配置复杂2、中断时间长3、资源利用率低4、依赖于redis数据节点5、主库压力比较大,性能有瓶颈

 

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance)该系统执行以下三个任务:

1、监控
Sentinel 会不断地定期检查你的主服务器和从服务器是否运作正常。
2、提醒
当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
3、自动故障迁移
当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从 服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失 效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器

目录规划
角色ip端口
Master 192.168.190.129 6379
Sentinel-01 192.168.190.129 26379
Master 192.168.190.128 6379
Sentinel-02 192.168.190.128 26379
Master 192.168.190.130 6379
Sentinel-03 192.168.190.130 26379
配置思路

哨兵是继续主从复制,所以先要配置好主从复制,具体步骤如下:

1、先配置和创建好1台服务器的节点和哨兵

2、使用传输命令发送到另外两台机器

3、修改另外两台机器的ip地址

实施过程
1、启动db01、db02、db03的redis节点,在db02、db03上执行主从复制的命令,并通过info replication命令查看主从状态
2、在各节点上执行以下命令创建哨兵的目录和配置文件,注意各节点的bind ip配置
mkdir -p /data/redis_cluster/redis_26379
mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
cat > /opt/redis_cluster/redis_26379/conf/redis_26379.conf<<EOF
bind 172.16.190.129
port 26379
##守护进程模式启动
daemonize yes
logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
dir /data/redis_cluster/redis_26379
#mymaster 是主节点别名 节点的ip 和端口 2是判断主节点失败,需要两个sentinel 节点同意
sentinel monitor mymaster 172.16.190.129 6379 2
#断线超时时间,超过这个时间就认为是断线
sentinel down-after-milliseconds mymaster 3000
#向新主节点发起复制操作的从节点个数,多个从同时传输会导致主节点服务器压力上升,写1则顺序复制,写总节点数则同时向主复制
sentinel parallel-syncs mymaster 1
#故障转移超时则判定为失败,设置值需要考虑网络环境、rdb备份文件大小
sentinel failover-timeout mymaster 18000
EOF
yum -y install rsync  #安装文件传输命令
启动哨兵,3台机器都操作
# redis-sentinel /opt/redis_cluster/redis_26379/conf/redis_26379.conf
[root@db01 ~]# ps -ef|grep redis
root   1633   1  0 09:49 ?    00:00:11 redis-server 127.0.0.1:6379
#26379端口服务变成了哨兵节点
root   4050   1  0 11:03 ?    00:00:00 redis-sentinel 172.16.190.129:26379 [sentinel]
[root@db01 conf]# more redis_26379.conf
#取消了sentinel down-after-milliseconds mymaster 3000默认配置。新增了纪元相关参数
bind 172.16.190.129
port 26379
daemonize yes
logfile "/opt/redis_cluster/redis_26379/logs/redis_26379.log"
dir "/data/redis_cluster/redis_26379"
sentinel monitor mymaster 172.16.190.129 6379 2
sentinel down-after-milliseconds mymaster 3000
sentinel failover-timeout mymaster 1800
# Generated by CONFIG REWRITE
protected-mode no
pidfile "/var/run/redis.pid"
user default on nopass ~* &* +@all
sentinel myid 93d33bce801f09b3172d22e7eb60c1a1e819e03d
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel current-epoch 0
sentinel known-replica mymaster 172.16.190.128 6379
sentinel known-sentinel mymaster 172.16.190.128 26379 86a2a69e6fd008214d42ace1fe
7dcef956d6196d
数据持续写入 观察日志变化,验证数据读取
故障模拟

1、停掉某个节点,观察其他节点日志变化

1、启动db01
2、启动哨兵
3、设置权重,db01大于其他节点
4、重新发起选举 redis-cli -h db01 -p 26379 Sentinelfailover mymaster
5、观察主从复制是否正常 #config get slaveof
6、恢复db01权重,下次公平选举

 

redis cluster

1、槽位分配slot
2、16384个槽位
3、每一个槽位都必须分配到位,有一个没有分配,整个集群都不可用
4、序号顺序不一定要连续,最重要的是每个节点的槽位梳理要大致相同,允许2%的误差
5、集群通讯端口为配置文件里的port加10000,比如6380的通讯端口就是16380
6、故障转移切换全自动,不需要人工干预
7、集群配置文件动态更新,不要手动修改
8、程序连接redis集群需要插件支持,插件版本要一致
9、集群内消息传递是同步的
10、集群内的所有一发现的节点配置文件是自动更新的
11、hash分配算法是足够随机和足够平均的 足够稳定
目录规划
# redis 安装目录 
/opt/redis_cluster/redis_{PORT}/{conf,logs,pid}
# redis 数据目录
/data/redis_cluster/redis_{PORT}/redis_{PORT}.rdb
# redis 运维脚本
/root/scripts/redis_shell.sh

拓扑图
 

 

手动搭建部署集群

部署一套服务器上的2个集群节点 ,发送完成后修改其他服务器的配置ip地址

 

##db01操作
mkdir -p /opt/redis_cluster/redis_{6380,6381}/{conf,logs,pid}
mkdir –p /data/redis_cluster/redis_{6380,6381}
cat >/opt/redis_cluster/redis_6380/conf/redis_6380.conf<<EOF
bind 172.16.190.129
port 6380
daemonize yes
pidfile "/opt/redis_cluster/redis_6380/pid/redis_6380.pid"
logfile "/opt/redis_cluster/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/data/redis_cluster/redis_6380/"
cluster-enabled yes
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
EOF

cp /opt/redis_cluster/redis_6380/conf/redis_6380.conf /opt/redis_cluster/redis_6381/conf/redis_6381.conf
sed -i 's#6380#6381#g' /opt/redis_cluster/redis_6381/conf/redis_6381.conf
rsync -avz /opt/redis_cluster/redis_638* db02:/opt/redis_cluster/
rsync -avz /opt/redis_cluster/redis_638* db03:/opt/redis_cluster/
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
###db02 操作
find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#129#128#g"
mkdir -p /data/redis_cluster/redis_{6380,6381}
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
###db03 操作
find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#129#130#g"
mkdir -p /data/redis_cluster/redis_{6380,6381}
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf

所有节点都启动后进程会有cluster标注,登录cluster nodes 查看每个节点只有自己,没有发现其他节点的信息,通过节点发现将其他节点的id自动写到集群配置文件内,redis除了原有的配置文件,又添加了一份配置文件,当集群信息发生变化,集群节点下线、故障转移等操作redis会自动记录在配置文件,不要手动修改集群的配置文件。

[root@db03 redis_cluster]# ps -ef|grep redis
root       2625      1  0 15:19 ?        00:00:00 redis-server 172.16.190.130:6381 [cluster]
root       2631      1  0 15:19 ?        00:00:00 redis-server 172.16.190.130:6380 [cluster]
[root@db03 redis_cluster]# redis-cli -h db03 -p 6380
db03:6380> CLUSTER nodes
d93ddcc484b2bef8462a7163436b95dcdcc20a35 :6380@16380 myself,master - 0 0 0 connected
[root@db03 ~]# sh redis_shell.sh login 6380  #登录集群内任意一台执行节点发现命令
172.16.190.130:6380> CLUSTER MEET 172.16.190.129 6381  #使用meet命令跟节点地址 发现对应节点
OK
172.16.190.130:6380> CLUSTER MEET 172.16.190.129 6380
OK
172.16.190.130:6380> CLUSTER MEET 172.16.190.128 6380
OK
172.16.190.130:6380> CLUSTER MEET 172.16.190.128 6381
OK
172.16.190.130:6380> CLUSTER MEET 172.16.190.130 6381
OK
172.16.190.130:6380> CLUSTER NODES  #查看集群节点信息
97d428a549976784f0b1e4a18895f611d7bb56d1 172.16.190.128:6381@16381 master - 0 1642666748131 4 connected
……

查看集群配置文件是否写入节点信息

[root@db02 redis_cluster]# cat redis_6381/nodes_6381.conf  --节点配置文件存储在数据目录
122d0aa0329a16ce11d62460ab57162f777761a4 172.16.190.129:6380@16380 master - 0 1642666710257 2 connected
46272fa2df81f4dac2f0c1ac54d68f6727baae69 172.16.190.128:6380@16380 master - 0 1642666709245 ……
redis集群通讯过程

分布式存储中需要提供维护节点元数据信息,元数据包括:节点负责哪些数据、是否出现故障灯状态信息;redis集群采用Gossip(流言)协议,协议工作原理就是节点不断交换信息。

1、集群中的每一个节点都会单独开辟一个tcp通道,用户节点之间彼此通信,通信端口在基础端口上佳1w
2、每个机电在固定周期内通过特定规则选择结构节点发送ping消息
3、接手到ping消息的节点用pong消息作为响应,集群中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点,也可能只知道部分节点,只要这些节点彼此可以正常通信,最终会形成一致状态,当节点出现故障、新节点加入、主从角色变化等,通过ping/pong达到部门消息的目的。
gossip协议常见消息分为:
ping: 用于检测节点是否在线及节点信息交换
pong:接手到ping、meet信息是给相应节点发送确认信息,也可以向集群发起广播自身费pong消息来通知整个集群对状态进行更新
meet:用于通知新节点加入
fail:当判定节点下线后通过广播向集群内发送fail消息,其他节点收到fail消息后也会更新对应节点状态未下线。

 

 

手动槽位分配

节点互相发现后需要分配槽位,并且所有槽位分配完毕后集群才可以使用,如果有一个槽位没有分配则整个集群不可用

[root@db03 ~]# sh redis_shell.sh login 6380
172.16.190.130:6380> set r3 1
(error) CLUSTERDOWN Hash slot not served  
172.16.190.130:6380> CLUSTER info   #查看集群状态
cluster_state:fail #
cluster_slots_assigned:0
……
redis-cli -h db01 -p 6380 cluster addslots {0..5461}
redis-cli -h db02 -p 6380 cluster addslots {5462..10922}
redis-cli -h db03 -p 6380 cluster addslots {10923..16383}
[root@db03 ~]# sh redis_shell.sh login 6380
172.16.190.130:6380> CLUSTER info
cluster_state:ok   #状态恢复

172.16.190.128:6380> CLUSTER nodes  #集群节点信息
46272fa2df81f4dac2f0c1ac54d68f6727baae69 172.16.190.128:6380@16380 myself,master - 0 1642678322000 3 connected 5462-10922
……
###节点信息解释
格式:<id> <ip:port> <flags> <master> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot> <slot> ... <slot>

id: 节点ID,是一个40字节的随机字符串,这个值在节点启动的时候创建,并且永远不会改变(除非使用CLUSTER RESET HARD命令)。
ip:port: 客户端与节点通信使用的地址.
flags: 逗号分割的标记位,可能的值有: myself, master, slave, fail?, fail, handshake, noaddr, noflags. 下一部分将详细介绍这些标记.
master: 如果节点是slave,并且已知master节点,则这里列出master节点ID,否则的话这里列出”-“。
ping-sent: 最近一次发送ping的时间,这个时间是一个unix毫秒时间戳,0代表没有发送过.
pong-recv: 最近一次收到pong的时间,使用unix时间戳表示.
config-epoch: 节点的epoch值(or of the current master if the node is a slave)。每当节点发生失败切换时,都会创建一个新的,独特的,递增的epoch。如果多个节点竞争同一个哈希槽时,epoch值更高的节点会抢夺到。
link-state: node-to-node集群总线使用的链接的状态,我们使用这个链接与集群中其他节点进行通信.值可以是 connected 和 disconnected.
slot: 哈希槽值或者一个哈希槽范围. 从第9个参数开始,后面最多可能有16384个 数(limit never reached)。代表当前节点可以提供服务的所有哈希槽值。如果只是一个值,那就是只有一个槽会被使用。如果是一个范围,这个值表示为起始槽-结束槽,节点将处理包括起始槽和结束槽在内的所有哈希槽。
#集群信息解释
172.16.190.130:6381> CLUSTER info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:7
cluster_my_epoch:6
cluster_stats_messages_ping_sent:16902
cluster_stats_messages_pong_sent:17202
cluster_stats_messages_fail_sent:4
cluster_stats_messages_auth-req_sent:5
cluster_stats_messages_sent:34113
cluster_stats_messages_ping_received:17197
cluster_stats_messages_pong_received:16897
cluster_stats_messages_fail_received:6
cluster_stats_messages_auth-req_received:1
cluster_stats_messages_auth-ack_received:2
cluster_stats_messages_received:34103
###########
cluster_state: ok状态表示集群可以正常接受查询请求。fail 状态表示,至少有一个哈希槽没有被绑定(说明有哈希槽没有被绑定到任意一个节点),或者在错误的状态(节点可以提供服务但是带有FAIL 标记),或者该节点无法联系到多数master节点。.
cluster_slots_assigned: 已分配到集群节点的哈希槽数量(不是没有被绑定的数量)。16384个哈希槽全部被分配到集群节点是集群正常运行的必要条件.
cluster_slots_ok: 哈希槽状态不是FAIL 和 PFAIL 的数量.
cluster_slots_pfail: 哈希槽状态是 PFAIL的数量。只要哈希槽状态没有被升级到FAIL状态,这些哈希槽仍然可以被正常处理。PFAIL状态表示我们当前不能和节点进行交互,但这种状态只是临时的错误状态。
cluster_slots_fail: 哈希槽状态是FAIL的数量。如果值不是0,那么集群节点将无法提供查询服务,除非cluster-require-full-coverage被设置为no .
cluster_known_nodes: 集群中节点数量,包括处于握手状态还没有成为集群正式成员的节点.
cluster_size: 至少包含一个哈希槽且能够提供服务的master节点数量.
cluster_current_epoch: 集群本地Current Epoch变量的值。这个值在节点故障转移过程时有用,它总是递增和唯一的。
cluster_my_epoch: 当前正在使用的节点的Config Epoch值. 这个是关联在本节点的版本值.
cluster_stats_messages_sent: 通过node-to-node二进制总线发送的消息数量.
cluster_stats_messages_received: 通过node-to-node二进制总线接收的消息数量.

 

集群高可用配置

为了防止一台机器故障整个集群不可用,启用对应从节点保障主节点故障时集群可用

###复制节点时避免本机主复制本机从,要复制其他机器的从节点
###从节点执行命令,表述自己要复制的节点id
redis-cli -h db01 -p 6381 CLUSTER REPLICATE 要复制的主节点id
redis-cli -h db01 -p 6381 CLUSTER REPLICATE 122d0aa0329a16ce11d62460ab57162f777761a4
redis-cli -h db02 -p 6381 CLUSTER REPLICATE 46272fa2df81f4dac2f0c1ac54d68f6727baae69
redis-cli -h db03 -p 6381 CLUSTER REPLICATE d93ddcc484b2bef8462a7163436b95dcdcc20a35
[root@db03 ~]# redis-cli -h db01 -p 6380 set t1 c 
(error) MOVED 8943 172.16.190.128:6380 #提示要在另外一台机器上插入数据,因为这个分片在168上
redis cluster ask路由

集群模式下redis在接收键值前会先计算键值对应的槽,如果是节点本身则处理,不是则恢复moved重定向错误,通知客户端请求正确的节点,这个过程成为mover重定向;

使用-c选项解决redis路由的问题
cat input_key.sh
#!/bin/bash
for i in $(seq 1 1000)
do
redis-cli -c -h db01 -p 6380 set k_${i} v_${i} && echo "set k_${i} is ok"
done
[root@db03 ~]# redis-cli -h db01 -c -p 6380
db01:6380> get k_1
"v_1"
db01:6380> get k_100
-> Redirected to slot [5541] located at 172.16.190.128:6380  #重定向到插槽[*]位于服务器
"v_100" #给了回复但也给了值
故障模拟转移

通过关闭单节点进程,查看其他节点日志变化及将节点从从节点恢复为主节点;

1、ps -ef|grep redis #查询进程id ,kill掉db03主节点
2、sh redis_shell.sh login 6381 #登录db03从节点,准备查询集群状态
3、172.16.190.130:6381> CLUSTER info
cluster_state:ok #杀掉进程后集群显示正常
4、172.16.190.130:6381> CLUSTER nodes
97d428a549976784f0b1e4a18895f611d7bb56d1 172.16.190.128:6381@16381 slave 46272fa2df81f4dac2f0c1ac54d68f6727baae69 0 1642749435000 3 connected #172.16.190.128:6381

46272fa2df81f4dac2f0c1ac54d68f6727baae69 172.16.190.128:6380@16380 master - 0 1642749434000 3 connected 5462-10922 #172.16.190.128:6380

6dcfd0d894189d2c02fbda110e63aeeb85209595 172.16.190.130:6381@16381 myself,master - 0 1642749435000 6 connected 10923-16383 #172.16.190.130:6381(原来的从)

d93ddcc484b2bef8462a7163436b95dcdcc20a35 172.16.190.130:6380@16380 slave,fail #状态异常 6dcfd0d894189d2c02fbda110e63aeeb85209595 1642749385493 1642749380000 6 disconnected
#172.16.190.130:6380
9f6e5453529bca33ce19b09c0d9771b52801af5d 172.16.190.129:6381@16381 slave 122d0aa0329a16ce11d62460ab57162f777761a4 0 1642749435225 2 connected  #172.16.190.129:6381@16381

122d0aa0329a16ce11d62460ab57162f777761a4 172.16.190.129:6380@16380 master - 0 1642749436240 2 connected 0-5461
#172.16.190.129:6380
4、 redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf #启动db02,观察集群状态
5、集群和节点状态正常,将6380切换为主
6、172.16.190.130:6380> CLUSTER FAILOVER
OK
172.16.190.130:6380> CLUSTER NODES
6dcfd0d894189d2c02fbda110e63aeeb85209595 172.16.190.130:6381@16381 master - 0 1642753513000 6 connected 10923-16383
d93ddcc484b2bef8462a7163436b95dcdcc20a35 172.16.190.130:6380@16380 myself,slave 6dcfd0d894189d2c02fbda110e63aeeb85209595 0 1642753514000 6 connected
……
172.16.190.130:6380> CLUSTER FAILOVER #想切换谁为主就在谁的节点和端口上执行
OK
172.16.190.130:6380> CLUSTER NODES
6dcfd0d894189d2c02fbda110e63aeeb85209595 172.16.190.130:6381@16381 slave d93ddcc484b2bef8462a7163436b95dcdcc20a35 0 1642753618153 8 connected
d93ddcc484b2bef8462a7163436b95dcdcc20a35 172.16.190.130:6380@16380 myself,master - 0 1642753616000 8 connected 10923-16383

 

错误锦集

故障描述:下班后所有虚拟机全部关闭,第二天通过通过命令启动集群,通过CLUSTER info查看集群状态未fail,节点状态如下:

redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
172.16.190.128:6380>CLUSTER NODES #节点状态fail
d93ddcc484b2bef8462a7163436b95dcdcc20a35 172.16.190.130:6380@16380 master,fail? - 1642729827554 1642729825606 0 connected 10923-16383
9f6e5453529bca33ce19b09c0d9771b52801af5d 172.16.190.129:6381@16381 slave,fail?
……
172.16.190.128:6380> CLUSTER info
cluster_state:fail #集群状态未fail
cluster_slots_assigned:16384
cluster_slots_ok:5461
cluster_slots_pfail:10923
cluster_slots_fail:0
……
172.16.190.128:6380> set y1 1 #数据插入显示集群未启动
(error) CLUSTERDOWN The cluster is down
####
redis-cli --cluster check 172.16.190.128:6380  #通过集群检查修复命令尝试修复集群
Could not connect to Redis at 172.16.190.129:6381: Connection timed out                                             Could not connect to Redis at 172.16.190.130:6381: No route to host #提示连接失败
Could not connect to Redis at 172.16.190.130:6380: No route to host
Could not connect to Redis at 172.16.190.129:6380: No route to host
172.16.190.128:6380 (46272fa2...) -> 327 keys | 5461 slots | 1 slaves.
[OK] 327 keys in 1 masters.
0.02 keys per slot on average.
>>> Performing Cluster Check (using node 172.16.190.128:6380)#进行集群检查
M: 46272fa2df81f4dac2f0c1ac54d68f6727baae69 172.16.190.128:6380
  slots:[5462-10922] (5461 slots) master #主,槽位
  1 additional replica(s)
S: 97d428a549976784f0b1e4a18895f611d7bb56d1 172.16.190.128:6381 #从,槽位
  slots: (0 slots) slave
  replicates 46272fa2df81f4dac2f0c1ac54d68f6727baae69 #复制节点数据
[OK] All nodes agree about slots configuration. #所有节点同意
>>> Check for open slots... #检查空槽位
>>> Check slots coverage... #检查槽位覆盖
[ERR] Not all 16384 slots are covered by nodes. #不是所有的槽位都被覆盖

####通过路由问题想到是防火墙策略未开放,除本机外的集群节点未检查,调整防火墙再次执行命令后集群状态正常
###不需要所有节点都执行检查命令 单节点执行即可    
使用工具搭建部署redis cluster

手动搭建可以了解过程和细节,但配置较多,多节点时工作量较大,官方提供了redis-trib.rb工具,redis-trib.rb 是采用 Ruby 实现的 redis 集群管理工具,内部通过 Cluster 相关命令帮我们简化集群 创建、检查、槽迁移和均衡等常见运维操作,使用前要安装 ruby 依赖环境。

安装命令:

#所有节点执行
yum makecache fast
yum install rubygems
gem sources --remove https://rubygems.org/
gem sources -a http://mirrors.aliyun.com/rubygems/
gem update –system
gem install redis -v 3.3.5
pkill redis
rm -rf /data/redis_cluster/redis_6380/*
rm -rf /data/redis_cluster/redis_6381/*
sh redis_shell.sh start 6380
sh redis_shell.sh start 6381
#db01执行
cd /opt/redis_cluster/redis/src/
redis-cli --cluster create 172.16.190.128:6381 172.16.190.130:6381 172.16.190.129:6381 172.16.190.128:6380 172.16.190.130:6380 172.16.190.129:6380 --cluster-replicas 1
#检查集群完整性
redis-cli --cluster check 172.16.190.129:6380
#####
请补充主从节点命令
错误锦集
[root@db01 src]# ./redis-trib.rb create --replicas 1 172.16.190.128:6381 172.16.190.130:6381 172.16.190.129:6381 172.16.190.128:6380 172.16.190.130:6380 172.16.190.129:6380
###该命令已被放弃
WARNING: redis-trib.rb is not longer available! #警告:redis-trib。Rb不再可用!
You should use redis-cli instead. 你应该使用redis-cli。
All commands and features belonging to redis-trib.rb have been moved
to redis-cli.#为了使用它们,你应该使用——cluster调用redis-cli
In order to use them you should call redis-cli with the --cluster
option followed by the subcommand name, arguments and options.#选项后面跟着子命令名、参数和选项。
Use the following syntax: #使用以下语法:
redis-cli --cluster SUBCOMMAND [ARGUMENTS] [OPTIONS]
Example: 举例
redis-cli --cluster create 172.16.190.128:6381 172.16.190.130:6381 172.16.190.129:6381 172.16.190.128:6380 172.16.190.130:6380 172.16.190.129:6380 --cluster-replicas 1
To get help about all subcommands, type: redis-cli --cluster help  #帮助命令
工具扩容节点

Redis 集群的扩容操作可分为以下几个步骤 1)准备新节点 2)加入集群 3)迁移槽和数据

扩容流程图:

db01上新建节点
mkdir -p /opt/redis_cluster/redis_{6390,6391}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6390,6391}
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6390/conf/redis_6390.conf
cp redis_6380/conf/redis_6380.conf redis_6391/conf/redis_6391.conf
sed -i 's#6380#6390#g' redis_6390/conf/redis_6390.conf
sed -i 's#6380#6391#g' redis_6391/conf/redis_6391.conf
启动节点
bash redis_shell.sh start 6390
bash redis_shell.sh start 6391
发现节点
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.51 6390
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.51 6391
在 db01 上使用工具扩容
cd /opt/redis_cluster/redis/src/
./redis-trib.rb reshard 10.0.0.51:6380

 

 

redis集群命令

集群(cluster)
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
节点(node)
CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。 CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
槽(slot)
CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节 点,那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。 CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
键(key)
CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。

 

redis运维工具

运维脚本
#!/bin/bash
USAG(){
echo "sh $0 {start|stop|restart|login|ps|tail} PORT"
}
if [ "$#" = 1 ]
then
   REDIS_PORT='6379'
elif
[ "$#" = 2 -a -z "$(echo "$2"|sed 's#[0-9]##g')" ]
then
   REDIS_PORT="$2"
else
USAG
exit 0
fi

REDIS_IP=$(hostname -I|awk '{print $1}')
PATH_DIR=/opt/redis_cluster/redis_${REDIS_PORT}/
PATH_CONF=/opt/redis_cluster/redis_${REDIS_PORT}/conf/redis_${REDIS_PORT}.conf
PATH_LOG=/opt/redis_cluster/redis_${REDIS_PORT}/logs/redis_${REDIS_PORT}.log
CMD_START(){
redis-server ${PATH_CONF}
}
CMD_SHUTDOWN(){
redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT} shutdown
}
CMD_LOGIN(){
redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT}
}

CMD_PS(){
   ps -ef|grep redis
}
CMD_TAIL(){
  tail -f ${PATH_LOG}
}
case $1 in
   start)
      CMD_START
      CMD_PS
      ;;
   stop)
      CMD_SHUTDOWN
CMD_PS
;;
restart)
      CMD_START
      CMD_SHUTDOWN
      CMD_PS
      ;;
  login)
      CMD_LOGIN
;;
    ps)
CMD_PS
;;
    tail)
    CMD_TAIL
    ;;
      *)
    USAG
esac
数据导入导出工具
cd /opt/redis_cluster/
git clone https://github.com/vipshop/redis-migrate-tool.git cd redis-migrate-tool/
autoreconf -fvi
./configure
make && make install
[root@db01 ~]# cat redis_6379_to_6380.conf 
[source]
type: single
servers:
- 10.0.0.51:6379
[target]
type: redis cluster
servers:
- 10.0.0.51:6380
[common]
listen: 0.0.0.0:8888
source_safe: true
生成测试数据
[root@db01 ~]# cat input_key.sh
#!/bin/bash
for i in $(seq 1 1000)
do
redis-cli -c -h db01 -p 6379 set k_${i} v_${i} && echo "set k_${i} is ok"
done
redis-migrate-tool -c redis_6379_to_6380.conf
redis-migrate-tool -c redis_6379_to_6380.conf -C redis_check
分析键值大小
yum install python-pip gcc python-devel
cd /opt/
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
python setup.py install
cd /data/redis_cluster/redis_6380/
rdb -c memory redis_6380.rdb -f redis_6380.rdb.csv
分析rdb并导出
awk -F ',' '{print $4,$2,$3,$1}' redis_6380.rdb.csv |sort > 6380.txt
监控过期键
需求背景
因为开发重复提交,导致电商网站优惠卷过期时间失效
问题分析
如果一个键已经设置了过期时间,这时候在 set 这个键,过期时间就会取消 解决思路
如何在不影响机器性能的前提下批量获取需要监控键过期时间
1.Keys* 查出来匹配的键名。然后循环读取ttl时间
2.scan * 范围查询键名。然后循环读取 ttl 时间
Keys 重操作,会影响服务器性能,除非是不提供服务的从节点
Scan 负担小,但是需要去多次才能取完,需要写脚本
cat 01get_key.sh
#!/bin/bash
key_num=0
> key_name.log
for line in $(cat key_list.txt)
do
while true
do
scan_num=$(redis-cli -h 192.168.47.75 -p 6380 SCAN ${key_num} match ${line}\* count
1000|awk 'NR==1{print $0}')
key_name=$(redis-cli -h 192.168.47.75 -p 6380 SCAN ${key_num} match ${line}\* count
1000|awk 'NR>1{print $0}')
echo ${key_name}|xargs -n 1 >> key_name.log
((key_num=scan_num))
if [ ${key_num} == 0 ]
then
      break
       fi
done
done

 

 

标签:6379,redis,笔记,学习,cluster,6380,172.16,节点
来源: https://www.cnblogs.com/xifange/p/15843905.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有