redis---缓存服务
mysql 关系型数据量
redis,mongo,es 非关系型数据量
一、redis基础
1、redis特点、
- 数据读取快,(数据都存放在内存中,使用C语言实现,使用单线程架构)
- 多种数据结构
- 功能丰富
- 简单稳定
- 客户端语言多
- 持久化
- 主从复制
- 高可用和分布式
2、应用场景
- 键过期功能: 缓存, session回话保存,优惠劵过期
- 列表:排行榜
- 天然计数器:浏览数、点击数、评论数
- 集合:兴趣标签、广告投放
- 消息队列: ELK
3、redis安装部署
- 目录规划:
redis下载目录
/tools/
redis安装目录
/opt/redis_cluster/redis_[port]/{conf,logs,pid}
redis数据目录
/data/redis_cluster/redis_[port]/redis_[port].rdb
redis运维脚本
/scripts/
- 部署安装:
#创建对应的目录
##6379为redis默认端口
mkdir -p /data/redis_cluster/redis_6379
mkdir -p /opt/redis_cluster/redis_6379/{conf,pid,logs}
mkdir /tools
#下载对应的软件包
cd /tools
wget https://download.redis.io/releases/redis-3.2.9.tar.gz
#解压对应的软件包到/opt/下
tar zxf redis-3.2.9.tar.gz -C /opt/redis_cluster/
#创建软连接,方便后续升级或者脚本维护
ln -s /opt/redis_cluster/redis-3.2.9/ /opt/redis_cluster/redis
#编译安装
cd /opt/redis_cluster/redis
make && make install
4、配置文件介绍
- 配置文件查找
找到对应的版本包,进入对应的目录下
redis-3.2.9/utils
执行对应的install_server.sh 根据提示 就可以再对应目录生成配置文件
- 本文使用配置文件
### 以守护进程模式启动
daemonize yes
### 绑定的主机地址(默认绑定内网网卡的地址)
bind 10.0.0.181
### 监听端口
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
- 启动关闭服务 ,
#启动
redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
#登录
#默认登录 127.0.0.1
redis-cli
#-h 指定ip登录
redis-cli -h ip
#关闭
#直接登录命令后面接 shutdown
redis-cli -h ip shutdown
#登录后,输入shutdown
redis-cli
shutdown
5、redis基础命令
- 全局命令
1、查看所有命键
keys *
# 十分危险命令,线上禁止使用,redis在内存中,数据量过大会导致redis直接卡死,挂掉
2、查看键的总数
DBSIZE
# dbsize命令在计算键总数是不会遍历所有键,而是直接获取redis内置的键总数的变量
3、检查键是否存在
EXISTS key
#如果键存在则返回1.不存在则返回0
4、删除键
DEL key [key ...]
# 通用命令,无论值是什么数据结构类型,del命令都可以将其删除
5、查看过期时间
#语法 TTL key
## TTL对应的值
-1 永不过期
-2 没有这个key
5、键过期时间设置
#语法 EXPIRE key seconds
db01:6379> EXPIRE k6 200
(integer) 1
db01:6379> TTL k6
(integer) 193
db01:6379> TTL k6
(integer) 193
db01:6379> TTL k6
(integer) 192
##生产事故注意 ,如果设置完过期时间,重新设置了key值,过期时间为永不失效
db01:6379> set k6 123
OK
db01:6379> TTL k6
(integer) -1
6、取消过期时间设置
#语法: PERSIST key
db01:6379> PERSIST k6
(integer) 1
db01:6379> TTL k6
(integer) -1
7、查询key的类型
#语法 TYPE key
db01:6379> TYPE k1
string
db01:6379> TYPE k2
string
- 字符串
1、设置一个key 并赋值
#语法 SET key value
db01:6379> set k1 2
OK
db01:6379> set k2 zhangxl
OK
2、查询key的值
#语法 GET key
db01:6379> get k1
"2"
db01:6379> get k2
"zhangxl"
3、设置多个key 并复制
#语法 MSET key value [key value ...]
db01:6379> MSET k4 4 k5 5 k6 6
OK
4、查询多个key
#语法 MGET key [key ...]
db01:6379> MGET k4 k5 k6
1) "4"
2) "5"
3) "6"
5、INCR 计数器。命令蒋字符串值解析成整数型,将其加1,最后结果保存为新的字符串,类似命令 INCRBY DECR DECRBY
db01:6379> SET K3 100
OK
db01:6379> GET K3
"100"
db01:6379> INCR K3
(integer) 101
db01:6379> INCR K3
(integer) 102
db01:6379> INCR K3
(integer) 103
db01:6379> INCRBY K3 1000
(integer) 1103
db01:6379> GET K3
"1103"
- 列表
1、添加列表元素
#从右插入列表元素
db01:6379> RPUSH list1 1
(integer) 1
db01:6379> RPUSH list1 2
(integer) 2
db01:6379> RPUSH list1 A
(integer) 3
db01:6379> RPUSH list1 B
(integer) 4
#从左插入列表元素
db01:6379> LPUSH list1 C
(integer) 5
db01:6379> LPUSH list1 D
(integer) 6
#批量插入列表元素
db01:6379> RPUSH list1 3 4 5 6 7 8
(integer) 10
db01:6379> LRANGE list1 0 -1
1) "C"
2) "1"
3) "2"
4) "A"
5) "3"
6) "4"
7) "5"
8) "6"
9) "7"
10) "8"
2、查看列表的元素
#查看列表的元素值 语法: LRANGE key start stop (查询所有 去一个不存在的反馈,查询单个 进行精确)
db01:6379> LRANGE list1 0 -1
1) "D"
2) "C"
3) "1"
4) "2"
5) "A"
6) "B"
db01:6379> LRANGE list1 0 1
1) "D"
2) "C"
db01:6379> LRANGE list1 0 0
1) "D"
#查看列表的元素数量
db01:6379> LLEN list1
(integer) 6
3、删除列表元素
#从右删除列表元素
db01:6379> RPOP list1
"B"
db01:6379> LRANGE list1 0 -1
1) "D"
2) "C"
3) "1"
4) "2"
5) "A"
#从左删除列表元素
db01:6379> lpop list1
"D"
db01:6379> LRANGE list1 0 -1
1) "C"
2) "1"
3) "2"
4) "A"
- 哈希
1、插入key数据
#语法: HMSET key field value [field value ...]
db01:6379> HMSET user:1000 name zxl age 28 job it
OK
2、查询key数据
###查询key指定的数据
#语法:HMGET key field [field ...]
db01:6379> HMGET user:1000 name
1) "zxl"
db01:6379> HMGET user:1000 name age job
1) "zxl"
2) "28"
3) "it"
###查询key所有的数据
#语法: HGETALL key
db01:6379> HGETALL user:1000
1) "name"
2) "zxl"
3) "age"
4) "28"
5) "job"
6) "it"
- 集合
1、设置集合的数据 (set集合不允许出现重复的元素)
#语法 SADD key member [member ...]
db01:6379> SADD set1 1 3 5 7 9
(integer) 5
db01:6379> SADD set2 1 3 5 2 4 6
(integer) 6
2、查询集合的数据
#语法 SMEMBERS key
db01:6379> SMEMBERS set1
1) "1"
2) "3"
3) "5"
4) "7"
5) "9"
db01:6379> SMEMBERS set2
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
3、删除集合指定的值
#语法 SREM key member [member ...]
db01:6379> SMEMBERS set2
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
db01:6379> SREM set2 1 3
(integer) 2
db01:6379> SMEMBERS set2
1) "2"
2) "4"
3) "5"
4) "6"
4、查询2个不同集合的差异数据 以第一个key为基准,找出第一个集合有 第二个集合没有 的数据
#语法
db01:6379> SDIFF set1 set2
1) "1"
2) "3"
3) "7"
4) "9"
db01:6379> SDIFF set2 set1
1) "2"
2) "4"
3) "6"
5、查询2个不同集合的并集数据
#语法 SINTER key [key ...]
db01:6379> SINTER set1 set2
1) "5"
6、查询2个不同集合的所有数据
#语法 SUNION key [key ...]
db01:6379> SUNION set1 set2
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "9"
6、数据持久化
- RDB持久化
#bgsave命令
db01:6379> BGSAVE
Background saving started
#查询之九华目录 已经存在对应的文件。再次关闭redis,打开数据还在 不会丢失,但是如果新插入数据,没有bgsave 新的数据丢失
- 优点
1、RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照,分成适用于备份,全量复制等场景,比如每6小时行bgsave本分,并把RBD文件拷贝到远程机器,用于灾难恢复
2、Redis加载RDB恢复数据远远快鱼AOF的方式
- 缺点
1、RDB方式数据没办法做到实时持久化,秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,行频繁成本过高
2、RDB文件使用特定二进制格式保存,Redis版本严禁过程中有多个格式的RDB版本,存在老版本Redis不兼容新版RDB格式的问题
- #配置文件添加指定的参数
### 指定本地持久化文件的文件名,默认是dump.rdb 指定多久发生变化保存 900秒 1个可以发生改变,保存
save 900 1 #900秒 发生一个key值改变
save 300 10 #300秒 发生10个key值改变
save 60 10000 #60秒 发生10000个key值改变
dbfilename redis_6379.rdb
###注意!!!!
- 如果什么条件都没达成,正常关闭了redis,后端会操作 bgsavs shutdown 数据会持久化
- 如果什么条件都没达成,kill pkill kill -15 优雅的关闭了redis,后端操作和正常关闭redis操作一直
- 如果什么条件都没达成,kill -9 关闭redis,程序会直接关闭,数据不会持久化,
- AOF持久化
- 工作流程
记录服务器执行的所有写操作命令,并在服务器启东市,通过重新执行这些命令来还原数据
AOF文件中的命令全部以Redis协议的格式来保存,新明路会被追加到文件的末尾
1、所有写入命令会追加到aof buf(缓冲区)
2、AOF缓冲区根据对应的策略想硬盘做同步操作
3、随着AOF文件越来越大,需要定期对AOF文件进行重写,大道压缩
4、当Redis服务重启时,可以加载AOF文件进行数据恢复
!!!如果存在aof和rdb备份同事存在,优先读取aof
- 缺点:
日志记录量比较大
- 有点:
安全。最多丢失1秒数据
- 配置文件:
#是否打开aof日志功能
appendonly yes
#每一个命令,都立即同步到aof
appendfsync always
#每秒写入一次
appendfsync everysec
#写入工作交给操作系统,由操作判断缓冲区大小,同意写入到aof
appendfsync no
#定义文件的名称
appendfilename "appendonly.aof"
- 面试问题
redis持久化方式有那些,有什么区别?
RDB : 基于快照的持久化,速度更快,一般用作备份,主从复制也是依赖于rdb持久化功能
AOF : 一追加的方式记录redis操作日志的文件,可以最大程度的保证redis数据安全,类似于mysql和binlog
7、redis 认证
- redis默认开启了保护模式,只允许本地会还地址登录并访问数据量
禁止 protected-mode
protected-mode yes/no (保护模式,是否只允许本地访问)
1)Bind:指定ip进行监听
vim /opt/redis_cluster/redis_6379/conf/redis_6379.conf
bind 10.0.0.181 127.0.0.1
2)增加requirepass {password}
requirepass 123456
#验证方法一:登录后输入目录,
[root@mariadb ~]# redis-cli -h db01
db01:6379> KEYS *
(error) NOAUTH Authentication required.
db01:6379> AUTH 123456
OK
db01:6379> KEYS *
996) "K_1643"
997) "K_1187"
998) "K_1812"
999) "K_1600"
1000) "K_1680"
1001) "K_1234"
1002) "K_1961"
1003) "K_1198"
#验证方法二:登录后面直接接密码
[root@mariadb ~]# redis-cli -h db01 -a 123456
db01:6379> KEYS *
996) "K_1643"
997) "K_1187"
998) "K_1812"
999) "K_1600"
1000) "K_1680"
1001) "K_1234"
1002) "K_1961"
1003) "K_1198"
架构
1、主从复制
- 备用服务器安装
#打包主服务器的配置,拷贝到从服务器
tar zcvf db01.tar.gz /opt/redis_cluster/
scp db01.tar.gz 172.16.214.185:/tools/
#解压,并执行make install 安装对应的命令
tar zxf /tools/db01.tar.gz -C /opt/
mv opt/* ./
#创建数据目录
mkdir -p /data/redis_cluster/redis_6379/
#修改对应的配置文件信息 ,修改对应的主机地址
bind 10.0.0.185
#启动对应的服务
redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
- 进行复制、同步
1、热备份
redis-cli -h 10.0.0.185
# 语法: SLAVEOF host port
SLAVEOF 10.0.0.181 6379
2、直接写入配置文件
slaveof 10.0.0.181 6379
3、取消主从 #生命没有任何关联
slaveof no one
- 主从同步流程
1、从库发起同步请求
2、主库收到请求后,执行bgsave保存当前内存里的数据到磁盘
3、主库蒋持久化的数据发送给从库的数据目录
4、从库收到主库的持久化数据后,先进行自己内存中的数据清楚
5、从库将逐鹿发送过来的持久化文件加载到自己的内存里
- 局限性:
1、执行主从复制之前,现将所有的数据都备份
2、建议将主从复制写入到配置文件
3、在业务低峰期做主从复制,
4、拷贝数据是会占用带宽
5、不能自动完成主从切换,需要人工接入
2、哨兵
- 主要功能
#介绍
Redis Sentinel 是一个分布式系统,Redis Sentinel为Redis提供高可用行.可以在没有认为敢于的情况下阻止某种类型的故障
#主要任务
1、监控
Sentinel会不断的定期检查你的主服务器和从服务器是否运作正常
2、提醒
当被监控的某个Redis服务器出现问题是,Sentinel可以通过api想管理员或者其他应用程序发送通知
3、自动故障迁移
当一个主服务器不能正常公职是,Sentinel会开始第一次自动故障迁移操作,他会将失效主服务器的其中一个从服务器升级为新的主服务器。并让失效主服务器的其他从服务器改为复制新的主服务器,当客户端师徒连接失效的主服务器是,集群也会想客户端返回新的主服务器地址,是的集群可以使用新的主服务器代替失效服务器.
- 环境准备,
准备1个主redis服务器,10.0.0.181 db01
准备2个从redis服务器,10.0.0.185/186 db02/db03
- 角色 目录规划
角色 ip 端口
Master 10.0.0.181 6379
Sentinel-01 26379
Master 10.0.0.185 6379
Sentinel-02 26379
Master 10.0.0.186 6379
Sentinel-03 26379
- 添加目录 创建配置文件,
DB01操作
mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
mkdir /data/redis_cluster/redis_26379
vim /opt/redis_cluster/redis_26379/conf/redis_26379.conf
bind 10.0.0.181
port 26379
daemonize yes
logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
dir /data/redis_cluster/redis_26379
#master 主节点别名 主节点ip和端口 判断主节点失败,2个sentinel节点同意
sentinel monitor mymaster 10.0.0.181 6379 2
#选项指定了sentinel认为服务器已经断线所需的毫秒数
sentinel down-after-milliseconds mymaster 3000
#向新的主节点发起复制操作的从节点个数
sentinel parallel-syncs mymaster 1
#故障转移超时时间
sentinel failover-timeout mymaster 18000
DB02操作
mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
mkdir /data/redis_cluster/redis_26379
vim /opt/redis_cluster/redis_26379/conf/redis_26379.conf
bind 10.0.0.185
port 26379
daemonize yes
logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
dir /data/redis_cluster/redis_26379
#master 主节点别名 主节点ip和端口 判断主节点失败,2个sentinel节点同意
sentinel monitor mymaster 10.0.0.181 6379 2
#选项指定了sentinel认为服务器已经断线所需的毫秒数
sentinel down-after-milliseconds mymaster 3000
#向新的主节点发起复制操作的从节点个数
sentinel parallel-syncs mymaster 1
#故障转移超时时间
sentinel failover-timeout mymaster 18000
DB03操作
mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
mkdir /data/redis_cluster/redis_26379
vim /opt/redis_cluster/redis_26379/conf/redis_26379.conf
bind 10.0.0.186
port 26379
daemonize yes
logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
dir /data/redis_cluster/redis_26379
#master 主节点别名 主节点ip和端口 判断主节点失败,2个sentinel节点同意
sentinel monitor mymaster 10.0.0.181 6379 2
#选项指定了sentinel认为服务器已经断线所需的毫秒数
sentinel down-after-milliseconds mymaster 3000
#向新的主节点发起复制操作的从节点个数
sentinel parallel-syncs mymaster 1
#故障转移超时时间
sentinel failover-timeout mymaster 18000
- 所有节点 启动redis 以及sentinel
redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
redis-sentinel /opt/redis_cluster/redis_26379/conf/redis_26379.conf
查看状态
[root@db01 redis_26379]# ps -ef | grep [r]edis
root 80698 1 0 10:06 ? 00:00:00 redis-server 10.0.0.181:6379
root 80756 1 0 10:10 ? 00:00:00 redis-sentinel 10.0.0.181:26379 [sentinel]
#查询哨兵的服务的配置文件,已经变更
[root@db01 conf]# cat /opt/redis_cluster/redis_26379/conf/redis_26379.conf
bind 10.0.0.181
port 26379
daemonize yes
logfile "/opt/redis_cluster/redis_26379/logs/redis_26379.log"
dir "/data/redis_cluster/redis_26379"
sentinel myid 22b4b5c975dec81d94d30eaf6b6c64935aef4647
sentinel monitor mymaster 10.0.0.181 6379 2
sentinel down-after-milliseconds mymaster 3000
sentinel failover-timeout mymaster 18000
# Generated by CONFIG REWRITE
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 10.0.0.186 6379
sentinel known-slave mymaster 10.0.0.185 6379
sentinel known-sentinel mymaster 10.0.0.186 26379 382bda458ef7099e18f2dda0000da990df51d3ee
sentinel known-sentinel mymaster 10.0.0.185 26379 c7cbb5c98a998e38bce3291c00428e8875ee8b27
sentinel current-epoch 0
- 哨兵常用操作API
#登录命令
redis-cli -h db01 -p 26379
#Sentinel节点是一个特殊的redis节点,他们有自己的专属API
Info Sentinel #查询相关主节点、哨兵节点的信息
Sentinel masters #查询所有master信息
Sentinel master #查询当前master组信息
Sentinel slaves #查询当前master组对应的slave信息
Sentinel sentinels #查询当前master组对应的sentinels信息
Sentinel get-master-addr-by-name #查询当前master节点对应的ip以及端口
- 模拟故障转移
#关闭redis主节点的服务,哨兵进行自动切换,
#查询从节点的日志 已经切换正常
35636:X 29 Sep 15:05:35.298 # +sdown master mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.299 # +sdown sentinel 22b4b5c975dec81d94d30eaf6b6c64935aef4647 10.0.0.181 26379 @ mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.371 # +odown master mymaster 10.0.0.181 6379 #quorum 2/2
35636:X 29 Sep 15:05:35.371 # +new-epoch 1
35636:X 29 Sep 15:05:35.371 # +try-failover master mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.372 # +vote-for-leader c7cbb5c98a998e38bce3291c00428e8875ee8b27 1
35636:X 29 Sep 15:05:35.378 # 382bda458ef7099e18f2dda0000da990df51d3ee voted for c7cbb5c98a998e38bce3291c00428e8875ee8b27 1
35636:X 29 Sep 15:05:35.473 # +elected-leader master mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.473 # +failover-state-select-slave master mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.565 # +selected-slave slave 10.0.0.186:6379 10.0.0.186 6379 @ mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.565 * +failover-state-send-slaveof-noone slave 10.0.0.186:6379 10.0.0.186 6379 @ mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.656 * +failover-state-wait-promotion slave 10.0.0.186:6379 10.0.0.186 6379 @ mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.748 # +promoted-slave slave 10.0.0.186:6379 10.0.0.186 6379 @ mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.748 # +failover-state-reconf-slaves master mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:35.815 * +slave-reconf-sent slave 10.0.0.185:6379 10.0.0.185 6379 @ mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:36.376 * +slave-reconf-inprog slave 10.0.0.185:6379 10.0.0.185 6379 @ mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:36.502 # -odown master mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:37.450 * +slave-reconf-done slave 10.0.0.185:6379 10.0.0.185 6379 @ mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:37.506 # +failover-end master mymaster 10.0.0.181 6379
35636:X 29 Sep 15:05:37.506 # +switch-master mymaster 10.0.0.181 6379 10.0.0.186 6379
35636:X 29 Sep 15:05:37.506 * +slave slave 10.0.0.185:6379 10.0.0.185 6379 @ mymaster 10.0.0.186 6379
35636:X 29 Sep 15:05:37.507 * +slave slave 10.0.0.181:6379 10.0.0.181 6379 @ mymaster 10.0.0.186 6379
35636:X 29 Sep 15:05:40.525 # +sdown slave 10.0.0.181:6379 10.0.0.181 6379 @ mymaster 10.0.0.186 6379
#在对应的哨兵查询目前的主节点
redis-cli -h db02 -p 26379
db02:26379> Sentinel get-master-addr-by-name mymaster
1) "10.0.0.186"
2) "6379"
#恢复主节点,之前的主节点已经是新的主节点的从
- 权重设置 强制指定性能比较好的服务器为主
Redis Sentinel存在多个节点是,如果想蒋指定的从节点晋升为主节点,可以将其他从吉尔碘的slavepriority配置为0,!!!但是需要注意failover后吗,蒋slave-priority调回原值。防止出现故障,无法切换
1、查询命令
CONFIG GET slave-priority
2、设置命令
CONFIG SET slave-priority 0
3、主动切换:(在需要切换成主的从节点的机器 哨兵运行改命令,强制故障切换)
sentinel failover mymaster
- 操作过程:
db02/db03操作
redis-cli -h db02 CONFIG GET slave-priority
1) "slave-priority"
2) "100"
redis-cli -h db02 CONFIG SET slave-priority 0
OK
redis-cli -h db02 CONFIG GET slave-priority
1) "slave-priority"
2) "0"
redis-cli -h db03 CONFIG GET slave-priority
1) "slave-priority"
2) "100"
redis-cli -h db03 CONFIG SET slave-priority 0
OK
redis-cli -h db03 CONFIG GET slave-priority
1) "slave-priority"
2) "0"
db01操作
redis-cli -h db01 -p 26379 Sentinel failover mymaster
OK
#查询现在的主节点:
redis-cli -h db01 -p 26379 Sentinel get-master-addr-by-name mymaster
1) "10.0.0.181"
2) "6379"
#修改db01和db02的slave-priority权重值为原值。
redis-cli -h db02 CONFIG SET slave-priority 100
redis-cli -h db02 CONFIG SET slave-priority 100
切换流程图
3、集群
- 介绍
Redis Cluster 是redis的分布式解决方案,在3.0版本正式推出、
当遇到单机、内存、并发、流量等瓶颈时 ,可以采用Cluster架构方案达到负载均衡木兰科
Redis Cluster 之前的分布式方案有2中:
1)客户端分区方案,有点分区逻辑可控,缺点是需要自己代码去处理数据路由
2)代理方案,有点建华客户端分布式逻辑和升级维护便利,缺点家中架构部署和性能消耗
- 目录规划
redis安装目录
/opt/redis_cluster/redis_[port]/{conf,logs,pid}
redis数据目录
/data/redis_cluster/redis_[port]/redis_[port].rdb
集群拓扑图
手动搭建部署集群
1)部署第一台服务器上的2个集群节点
2)发送完成后修改其他主机的ip地址
3)ansible批量部署
实现命令:
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 <
DB02操作
find /opt/redis_cluster/redis_638* -type f -name "*.conf" | xargs sed -i "/bind/s#181#185#g"
mkdir -p /data/redis_cluster/redis_{6380,6381}
DB03操作:
find /opt/redis_cluster/redis_638* -type f -name "*.conf" | xargs sed -i "/bind/s#181#186#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
- 手动配置集群发现 任意节点执行
#添加集群发现
10.0.0.181:6380> CLUSTER MEET 10.0.0.181 6381
OK
#查询集群节点
CLUSTER NODES
a68f6869238d307f63d14d1c319ce4ff22228455 10.0.0.185:6380 master - 0 1601435619729 0 connected
9cbb441f5c95d3f4a79a95e451416203b5d91efc 10.0.0.186:6381 master - 0 1601435617706 4 connected
966b0c81209f90f49cacf33121739d19bead0f1d 10.0.0.185:6381 master - 0 1601435618713 3 connected
9f61bf0f2021832583c5c05448362ddad59adec5 10.0.0.181:6381 master - 0 1601435616701 5 connected
31ffed5fe6da5ccb2b96b9e67d92b8659dd703de 10.0.0.181:6380 myself,master - 0 0 1 connected
657ee92eea8040ce69c20afb0ed8070ba652cafa 10.0.0.186:6380 master - 0 1601435617204 2 connected
- Redis Cluster通讯流程
1)集群中每一个节点都会单独开辟一个TCP通道,用于节点之前的批次通信,通信端口在基础端口上加10000
2)每个节点在固定周期内通过特定规则选择结构点发送ping消息
3)接收到ping消息的节点用pong消息作为相应,汲取中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点,也可能仅知道部分节点,只要这些节点批次可以正常通信,最终他们回达成一致的桩体,当节点出现故障,新节点接入,主从角色变化等,它能够不断的ping/pong消息,从而达到同步目的 - 槽位分配-主从配置
#查询槽位
10.0.0.181:6380> CLUSTER info
cluster_state:fail #没有槽位
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:0
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_sent:2776
cluster_stats_messages_received:2776
#分配槽位
1)手动分配槽位
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}
2)工具
......
#配置主从
#查看节点、
[root@db01 scripts]# redis-cli -h db01 -p 6380 cluster nodes | awk '/6380/{print $1,$2}'
a68f6869238d307f63d14d1c319ce4ff22228455 10.0.0.185:6380
31ffed5fe6da5ccb2b96b9e67d92b8659dd703de 10.0.0.181:6380
657ee92eea8040ce69c20afb0ed8070ba652cafa 10.0.0.186:6380
#创建复制关系
redis-cli -h db01 -p 6381 cluster REPLICATE a68f6869238d307f63d14d1c319ce4ff22228455
OK
redis-cli -h db02 -p 6381 cluster REPLICATE 657ee92eea8040ce69c20afb0ed8070ba652cafa
OK
redis-cli -h db03 -p 6381 cluster REPLICATE 657ee92eea8040ce69c20afb0ed8070ba652cafa
OK
#插入数据
db01:6381> set 1 11
(error) MOVED 9842 10.0.0.185:6380
redis-cli -h db02 -p 6380
db02:6380> keys *
(empty list or set)
db02:6380> set 1 111
OK
#加入-c 插入数据后,自动识别到目标节点.
db01:6380> set 123 123
(error) MOVED 5970 10.0.0.185:6380
[root@db01 ~]# redis-cli -h db01 -p 6380 -c
db01:6380> set 123 123
-> Redirected to slot [5970] located at 10.0.0.185:6380
OK
- 故障转移
关闭掉一台住的机器,自动转移到从.
可以同时坏掉一台机器一个从服务 或者 3个主服务
4、集群构建工具
- redos-trib.rb 采用Ruby实现的redis集群管理工具,内部通过Cluster相关命令帮我们简化集群创建、检查、槽迁移金额均衡等常见运维操作,使用前需要先安装ruby依赖环境
- 安装命令
yum makecache fast #更新缓存
yum install rubygems #安装ruby
gem sources --remove https://rubygems.org/ #溢出ruby源,
gem sources -a http://mirrors.aliyun.com/rubygems/ #添加ruby 阿里云源
gem update - system #更新系统
gem install redis -v 3.2.9 #安装依赖 (报错查看文档 https://blog.csdn.net/weixin_30344995/article/details/95782570 yum update -y nss curl libcurl)
#我们可以停掉所有的节点,然后清空数据,恢复成一个全新的集群,所有机器执行命令
pkill redis
rm -rf /data/redis_cluster/redis_6380/*
rm -rf /data/redis_cluster/redis_6381/*
#全部清空之后启动所有的节点,所有机器执行
sh redis.sh start 6380
sh redis.sh start 6381
#db01执行创建集群命令
./redis-trib.rb create --replicas 1 10.0.0.181:6380 10.0.0.181:6381 10.0.0.185:6380 10.0.0.185:6381 10.0.0.186:6380 10.0.0.186:6381
#之后输入yes(注意 自动生成的集群,主从存在本机复制本机现象,需要调整主从关系)
redis-cli -h db02 -p 6381 cluster REPLICATE 657ee92eea8040ce69c20afb0ed8070ba652cafa
OK
redis-cli -h db03 -p 6381 cluster REPLICATE 657ee92eea8040ce69c20afb0ed8070ba652cafa
OK
# 检查集群完整性
./redis-trib.rb check 10.0.0.181:6380
>>> Performing Cluster Check (using node 10.0.0.181:6380)
M: d3add0da8168198cb47d28e98a233b1c9166e3ec 10.0.0.181:6380
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: e26989d9ff1d513aa361e74e217c47a4a85fd0d3 10.0.0.181:6381
slots: (0 slots) slave
replicates 4b910222cc4a6b73a852044d1e3f00a8ff3b58a5
M: 4b910222cc4a6b73a852044d1e3f00a8ff3b58a5 10.0.0.185:6380
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 985f6b06a6b057fcf970b0793f60d5a66721cf62 10.0.0.185:6381
slots: (0 slots) slave
replicates 7c10f584f9cae265c95b5d3e5149c4b88dca9ec9
M: 7c10f584f9cae265c95b5d3e5149c4b88dca9ec9 10.0.0.186:6380
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: eb858cba15f73853124d5f5d6e1d2c9c83c2fa1f 10.0.0.186:6381
slots: (0 slots) slave
replicates d3add0da8168198cb47d28e98a233b1c9166e3ec
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# 检查集群负载情况
./redis-trib.rb rebalance 10.0.0.185:6380
>>> Performing Cluster Check (using node 10.0.0.185:6380)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.0% threshold.
5、扩容收缩
- 生产环境中,不手动扩容.
- 工具扩容节点
Redis集群的扩容操作可分为以下几个步骤
1)准备新节点
2)加入集群
3)迁移槽和数据
扩容流程图:
##我们在db01上创建2个新节点
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
#启动节点
redis-server /opt/redis_cluster/redis_6390/conf/redis_6390.conf
redis-server /opt/redis_cluster/redis_6391/conf/redis_6391.conf
#发现节点(手动)
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.181 6390
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.181 6391
#工具发现节点
cd /opt/redis_cluster/redis/src/
./redis-trib.rb add-node 10.0.0.181:6390 10.0.0.181:6380
./redis-trib.rb add-node 10.0.0.181:6391 10.0.0.181:6380
#扩容、分配迁移槽
cd /opt/redis_cluster/redis/src/
./redis-trib.rb reshard 10.0.0.181:6380(注意 有交互,16384个槽 #4个节点 计算每个节点的槽位,输入)
打印出进群每个节点信息后,reshard命令需要确认迁移的槽数量,这里我们输入4096个:
How many slots do you want to move (from 1 to 16384)? 4096
输入6390的节点ID作为目标节点,也就是要扩容的节点,目标节点只能指定一个
What is the receiving node ID? xxxxxxxxx
之后输入源节点的ID,这里分别输入每个主节点的6380的ID最后输入done,或者直接输入all
Source node #1:all
###4096是: redis的总槽位是16384个 需要分配到每个节点的槽位 ##这里4个master节点,所以16384/4=4096
#第二项:是需要转移槽位到那个节点
#第三项:是那些节点的槽位转移到新的节点,可以手动输入3个#Master节点的ID 然后输入done,或者直接输入all 所有的master节点
#第四项:输入yes开始转移
#迁移完成后命令会自动退出,这时候我们查看一下集群的状态
./redis-trib.rb rebalance 10.0.0.51:6380
###注意出现报错 可能是gem对应的redis版本问题,可以重新安装redis的版本为3.2.2
gem list
gem uninstall redis -v 4.2.2
gem install redis-3.2.2.gem
-
工具收缩节点
流程说明 1).首先需要确定下线节点是否有负责的槽, 如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性. 2).当下线节点不再负责槽或者本身是从节点时, 就可以通知集群内其他节点忘记下线节点,当所有的节点忘记该节点后可以正常关闭. 这里我们准备将刚才新添加的节点下线,也就是6390和6391 收缩和扩容迁移的方向相反,6390变为源节点,其他节点变为目标节点,源节点把自己负责的4096个槽均匀的迁移到其他节点上,. 由于redis-trib..rb reshard命令只能有一个目标节点,因此需要执行3次reshard命令,分别迁移1365,1365,1366个槽.
#操作命令:
cd /opt/redis_cluster/redis/src/
./redis-trib.rb reshard 10.0.0.181:6380
How many slots do you want to move (from 1 to 16384)? 1365 #(1365这个值是集群是4-1 剩余3个节点,要删除的节点的槽位数是4096除以3 的值)
#输入6380的id
#输入6390的id
done
- 忘记节点
#由于我们的集群是做了高可用的,所以当主节点下线的时候从节点也会顶上,所以最好我们先下线从节点,然后在下线主节点
cd /opt/redis_cluster/redis/src/
./redis-trib.rb del-node 10.0.0.51:6391 ID
./redis-trib.rb del-node 10.0.0.51:6390 ID
6、redis常用运维工具
运维脚本 redis.sh
数据导入导出工具
刚切换到redis集群的时候肯定会面临数据导入的问题,所以这里推荐使用redis-migrate-tool工具来导入单节点数据到集群里
#安装工具
cd /opt/redis_cluster/
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool/
autoreconf -fvi
./configure
make && make install
#创建配置文件 ##源节点 目标节点
cat > redis_6379_to_6380.conf <
- 分析键值大小
#说明 :redis的内存使用太大键值太多,不知道哪些键值占用的容量比较大,而且在线分析会影响性能.
#安装工具
yum install python-pip gcc python-devel
cd /opt/
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
python2.7 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
故障案列:
- 常见故障案列
redis动态调整内存故障
config get maxmemory
config set maxmemory
动态内存调整只能调整的比实际占用的大,不能调整的比实际占用的小,不然就会报错
动态调整的参数不会写入到配置文件里,配置文件里也看不到最大内存使用限制,及时重启,动态配置也会生效,只能通过config get maxmemory和config set maxmemory 0 (不限制内存使用)来恢复配置
redis默认启动不限制内存,线上环境,建议限制redis的最大使用内存为服务器的50%,
内存占用满之后,
- 惰性删除
- 随机删除
- 什么都不做(默认)
maxmemory
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes