Redis命令、持久化、主从复制
redis配置
- Redis命令、持久化、主从复制
- Redis数据类型
- redis数据库常用命令
- redis多数据库常用命令
- 1、多数据库间切换
- 2、多数据库间移动数据
- 3、清除数据库内数据
- key命令
- 1、keys 命令
- 2、判断键值是否存在exists
- 3、删除当前数据库的指定key del
- 4、获取key对应的value值类型 type
- 5、设置key过期时间
- 6、查看有效时间,以秒为单位
- 7、对key重命名
- 7.5、renamenx
- 8、查看当前数据库中key的数目 dbsize
- 9、使用config set requirepass yourpassword命令设置密码
- 10、使用config get requirepass命令查看密码
- 11、删除密码
- string类型
- 增加、修改
- 获取
- 删除
- hash类型
- 增加、修改
- 删除
- list类型
- 增加
- 获取
- 删除
- set类型
- 增加
- 获取
- 删除
- zset类型
- 增加
- 获取
- 删除
- 使用5种数据类型用来描述角色信息
- Redis高可用-持久化
- RDB持久化
- AOF 持久化
- Redis高可用-集群
- 主从复制部署
- 搭建redis主从复制集群,2个集群6台主机
- 级联主从
- 配置定时任务,免交互删除redis中的key
Redis数据类型
redis每条数据都是⼀个键值对,值的类型分为五种:
- 字符串string
- 哈希hash
- 列表list
- 集合set
- 有序集合zset
redis数据库常用命令
set:存放数据,命令格式 set key value
get:获取数据,命令格式 get key
redis多数据库常用命令
redis支持多数据库,redis默认情况下包含16个数据库,数据库名称是用数字0-15来依次命名的。
多数据库相互独立,互不干扰
1、多数据库间切换
命令格式:select 序号
#使用redis-cli连接redis数据库后,默认使用的是序号为0的数据库
2、多数据库间移动数据
命令格式:move 键值 序号
3、清除数据库内数据
FLUSHDB:清空当前数据库数据
FLUSHALL:清空所有数据库的数据
#千万慎用!!!!
key命令
1、keys 命令
#keys 命令可以取符合规则的键值列表,通常情况可以结合*、?等选项来使用。
keys * #查看当前数据库中所有的数据
keys v* #查看当前数据库中以v开头的数据
keys v?? #查看当前数据库中以v开头后面包含任意一位的数据
keys v?? #查看当前数据库中以v开头后面包含任意两位的数据
2、判断键值是否存在exists
语法 exists [键]
返回值为1则存在,为0则不存在
3、删除当前数据库的指定key del
语法 del [键]
4、获取key对应的value值类型 type
语法 type [键]
5、设置key过期时间
设置过期时间,以秒为单位
如果没有指定过期时间则⼀直存在,直到使⽤DEL移除
语法:expire key seconds
例:设置键’a1’的过期时间为3秒 expire a1 3
查看key有效时间
6、查看有效时间,以秒为单位
语法:ttl key
7、对key重命名
对已有 key 进行重命名
语法:rename 源key 目标key
例:将key a1改为b1
rename a1 b1
7.5、renamenx
命令的作用是对已有 key 进行重命名,并检测新名是否存在,如果目标 key 存在则不进行重命名。(不覆盖)
命令格式:
renamenx 源key 目标key
8、查看当前数据库中key的数目 dbsize
命令格式:dbsize
9、使用config set requirepass yourpassword命令设置密码
命令格式 config set requirepass 密码
10、使用config get requirepass命令查看密码
#一旦设置密码,必须先验证通过密码,否则所有操作不可用
auth 123456
config get requirepass
11、删除密码
auth 123456 #因为之前设置过密码,所以要先登录
config set requirepass '' #用''代表空密码
string类型
增加、修改
如果设置的键不存在则为添加,如果设置的键已经存在则修改
设置键值 set key value
#例1:设置键为name值为zhangsan的数据
set name zhangsan
设置键值及过期时间,以秒为单位 setex key seconds value
#例2:设置键为aa值为aa过期时间为3秒的数据
setex aa 3 aa
设置多个键值 mset key1 value1 key2 value2 …
#例3:设置键为'a1'值为'Python'、键为'a2'值为'Java'、键为'a3'值为'c'
mset a1 python a2 java a3 c
追加值 append key value
#例4:向键为a1中追加值' haha'
append a1 haha
获取
获取:根据键获取值,如果不存在此键则返回nil
get key
#例5:获取键'name'的值
get name
根据多个键获取多个值 mget key1 key2 …
#例6:获取键a1、a2、a3'的值
mget a1 a2 a3
删除
删除键及对应的值 del key1 key2 …
#例7:删除键a2、a3
del a2 a3
hash类型
- hash⽤于存储对象,对象的结构为属性、值
- 值的类型为string
增加、修改
设置单个属性 hset key field value
# 例1:设置键 user的属性name为zhangsan
hset user name zhangsan
设置多个属性 hmset key field1 value1 field2 value2 ...
#例2:设置键u2的属性name为zhangsan、属性age为11
hmset u2 name zhangsan age 11
获取
获取指定键所有的属性 hkeys key
#例3:获取键u2的所有属性
hkeys u2
获取⼀个属性的值 hget key field
#例4:获取键u2属性'name'的值
hget u2 name
获取多个属性的值 hmget key field1 field2 …
#例5:获取键u2属性'name'、'age的值
hmget u2 name age
获取所有属性的值 hvals key
#例6:获取键'u2'所有属性的值
hvals u2
删除
删除整个hash键及值,使⽤del命令
删除属性,属性对应的值会被⼀起删除 hdel key field1 field2 …
#例7:删除键'u2'的属性'age'
hdel u2 age
list类型
- 列表的元素类型为string
- 按照插⼊顺序排序
增加
在左侧插⼊数据 lpush key value1 value2 …
#例1:从键为'a1'的列表左侧加⼊数据a 、 b 、c
lpush a1 a b c
在右侧插⼊数据 rpush key value1 value2 …
#例2:从键为'a1'的列表右侧加⼊数据0 1
rpush a1 0 1
在指定元素的前或后插⼊新元素 linsert key before或after 现有元素 新元素
#例3:在键为'a1'的列表中元素'b'前加⼊'3'
linsert a1 before b 3
获取
返回列表⾥指定范围内的元素 start、stop为元素的下标索引
索引从左侧开始,第⼀个元素为0
索引可以是负数,表示从尾部开始计数,如-1表示最后⼀个元素
lrange key start stop
#例4:获取键为'a1'的列表所有元素
lrange a1 0 -1
设置指定索引位置的元素值
- 索引从左侧开始,第⼀个元素为0
- 索引可以是负数,表示尾部开始计数,如-1表示最后⼀个元素
lset key index value
#例5:修改键为'a1'的列表中下标为1的元素值为'z'
lset a1 1 z
删除
- 删除指定元素
- 将列表中前count次出现的值为value的元素移除
- count > 0: 从头往尾移除
- count < 0: 从尾往头移除
- count = 0: 移除所有
lrem key count value
#例6.1:向列表'a2'中加⼊元素'a'、'b'、'a'、'b'、'a'、'b'
lpush a2 a b a b a b
#例6.2:从'a2'列表右侧开始删除2个'b'
lrem a2 -2 b
#例6.3:查看列表'py12'的所有元素
lrange a2 0 -1
lpop 移除并返回列表的第一个元素
lpop key
rpop 移除列表的最后一个元素,返回值为移除的元素
rpop key
set类型
- ⽆序集合
- 元素为string类型
- 元素具有唯⼀性,不重复
- 说明:对于集合没有修改操作
增加
添加元素 sadd key member1 member2 …
#例1:向键'a3'的集合中添加元素'linuxmi'、'lisi'、'linuxidc'
sadd a3 linuxmi sili linuxidc
获取
返回所有的元素 smembers key
#例2:获取键'a3'的集合中所有元素
smembers a3
删除
删除指定元素 srem key
#例3:删除键'a3'的集合中元素'linuxidc'
srem a3 linuxidc
移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素
spop key [count]
zset类型
- sorted set,有序集合
- 元素为string类型
- 元素具有唯⼀性,不重复
- 每个元素都会关联⼀个double类型的score,表示权重,通过权重将元素从⼩到⼤排序
- 说明:没有修改操作
增加
添加 zadd key score1 member1 score2 member2 …
#例1:向键'a4'的集合中添加元素'lisi'、'linuxidc'、'muu'、'linuxmi',权重分别为4、5、6、3
zadd a4 4 lisi 5 linuxidc 6 muu 3 linuxmi
获取
返回指定范围内的元素
start、stop为元素的下标索引
索引从左侧开始,第⼀个元素为0
索引可以是负数,表示从尾部开始计数,如-1表示最后⼀个元素 zrange key start stop
#例2:获取键'a4'的集合中所有元素
zrange a4 0 -1
返回score值在min和max之间的成员 zrangebyscore key min max
#例3:获取键'a4'的集合中权重值在5和6之间的成员
zrangebyscore a4 5 6
返回成员member的score值 zscore key member
#例4:获取键'a4'的集合中元素'linuxmi'的权重
zscore a4 linuxmi
删除
删除指定元素 zrem key member1 member2 …
#例5:删除集合'a4'中元素'linuxmi'
zrem a4 linuxmi
删除权重在指定范围的元素 zremrangebyscore key min max
#例6:删除集合'a4'中权重在5、6之间的元素
zremrangebyscore a4 5 6
使用5种数据类型用来描述角色信息
Lillia ATK 61 Armor 20 Spell 32 HP 580
string:
set Lillia "{\"ATK\": \"61\",\"Armor\": \"20\",\"Spell\": \"32\",\"HP\": \"580\"}"
hash
HMSET Lillia1 ATK 61 Armor 20 Spell 32 HP 580
list
RPUSH Lillia2 "\"ATK\":61" "\"Armor\":20" "\"Spell\":32" "\"HP\":580"
set
SADD Lillia3 "\"ATK\":61" "\"Armor\":20" "\"Spell\":32" "\"HP\":580"
zset
ZADD Lillia4 20 Armor 580 HP 32 Spell 61 ATK
Redis高可用-持久化
1、持久化的功能
(1)Redis是内存数据库,数据都是存储在内存中,为了避免服务器断电等原因导致Redis进程异常退出后数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复
(2)除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置
2、两种持久化方式
(1)RDB 持久化:原理是将Redis在内存中的数据库记录定时保存到磁盘上(有点像快照)
(2)AOF 持久化:原理是将Reids的操作日志以注:追加的方式写入文件,类似于MySQL的binlog(类似于历史记录)
由于AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,因此AOF是目前主流的持久化方式,不过RDB持久化仍然有其用武之地
tips
进程与线程的区别总结:本质区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。
包含关系:一个进程至少有一个线程,线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
资源开销:每个进程都有独立的地址空间,进程之间的切换会有较大的开销;线程可以看做轻量级的进程,同一个进程内的线程共享进程的地址空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。
影响关系:一个进程崩溃后,在保护模式下其他进程不会被影响,但是一个线程崩溃可能导致整个进程被操作系统杀掉,所以多进程要比多线程健壮。
RDB持久化
1、概述
(1)RDB持久化是指在指定的时间间隔内将内存中当前进程中的数据生成快照保存到硬盘(因此也称作快照持久化),用二进制压缩存储,保存的文件后缀是rdb
(2)当Redis重新启动时,可以读取快照文件恢复数据
2、触发条件
(1)手动触发
- save命令和bgsave命令都可以生成RDB文件
save命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在Redis服务器阻塞期间,服务器不能处理任何命令请求
- bgsave命令会创建一个子进程,由子进程来负责创建RDB文件,父进程(即Redis主进程)则继续处理请求
bgsave命令执行过程中,只有fork子进程时会阻塞服务器,而对于save命令,整个过程都会阻塞服务器,因此save已基本被废弃,线上环境要杜绝save的使用
(2)自动触发
• 在自动触发RDB持久化时,Redis也会选择bgsave而不是save来进行持久化
• 自动触发最常见的情况是在配置文件中通过save m n,指定当m秒内发生n次变化时,会触发bgsave
vim /etc/redis/6379.conf
#----219行----以下三个save条件满足任意一个时,都会引起bgsave的调用
save 900 1 :当时间到900秒时,如果redis数据发生了至少1次变化,则执行bgsave
save 300 10 :当时间到300秒时,如果redis数据发生了至少10次变化,则执行bgsave
save 60 10000 :当时间到60秒时,如果redis数据发生了至少10000次变化,则执行bgsave
#----242行----是否开启RDB文件压缩
rdbcompression yes
#----254行----指定RDB文件名
dbfilename dump.rdb
#----264行----指定RDB文件和AOF文件所在目录
dir /var/lib/redis/6379
(3)其他自动触发机制
• 除了save m n 以外,还有一些其他情况会触发bgsave
• 在主从复制场景下,如果从节点执行全量复制操作,则主节点会执行bgsave命令,并将rdb文件发送给从节点
• 执行shutdown命令时,自动执行rdb持久化
3、bgsave工作流程
(1)Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof的子进程,如果在执行则bgsave命令直接返回。 bgsave/bgrewriteaof的子进程不能同时执行,主要是基于性能方面的考虑:两个并发的子进程同时执行大量的磁盘写操作,可能引起严重的性能问题
(2)父进程执行fork操作创建子进程,这个过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令
(3)父进程fork后,bgsave命令返回"Background saving started"信息并不再阻塞父进程,并可以响应其他命令
(4)子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换
(5)子进程发送信号给父进程表示完成,父进程更新统计信息
4、启动时加载
(1)RDB文件的载入工作是在服务器启动时自动执行的,并没有专门的命令。但是由于AOF的优先级更高,因此当AOF开启时,Redis会优先载入 AOF文件来恢复数据;只有当AOF关闭时,才会在Redis服务器启动时检测RDB文件,并自动载入。服务器载入RDB文件期间处于阻塞状态,直到载入完成为止
(2)Redis(AOF关闭的时候)载入RDB文件时,会对RDB文件进行校验,如果文件损坏,则日志中会打印错误,Redis启动失败
AOF 持久化
1、概述
(1)RDB持久化是将进程数据写入文件,而AOF持久化,则是将Redis执行的每次写、删除命令记录到单独的日志文件中,查询操作不会记录; 当Redis重启时再次执行AOF文件中的命令来恢复数据
(2)与RDB相比,AOF的实时性更好,因此已成为主流的持久化方案
AOF工作流程
(1)客户端的请求写命令会被append追加到AOF缓冲区内;
(2)AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中;
(3)AOF文件大小超过重写策略或手动重写时,会对AOF文件进行rewrite重写,压缩AOF文件容量;
(4)Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的;
Redis服务器默认开启RDB,关闭AOF;要开启AOF,需要在配置文件中配置:
vim /etc/redis/6379.conf
#----700行----修改;开启AOF
appendonly yes
#----704行----指定AOF文件名称
appendfilename "appendonly.aof"
#----796行----是否忽略最后一条可能存在问题的指令
aof-load-truncated yes
#指redis在恢复时,会忽略最后一条可能存在问题的指令,默认为yes,即在aof写入时,可能存在指令错误的问题(突然断电导致未执行结束),这种情况下,yes会log并继续,而no会直接恢复失败
AOF写数据策略(appendfsync)
aof写数据三种策略
- always(每次)
每次写入操作均同步到AOF文件中,数据零误差,性能较低 - everysec(每秒)
每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高
在系统突然宕机的情况下丢失1秒内的数据 - no(系统控制)
由操作系统控制每次同步到AOF文件的周期,整体过程不可控
RDB和AOF的优先级
前提:
- 因为redis默认将数据保存在内存中,所以redis启动、关闭时内存中的数据会丢失
- 在redis每次启动时,都会读取持久化文件,将数据恢复到内存中,以保证redis数据完整性
RDB和AOF优先级,AOF优先级高
Redis高可用-集群
1、概述
(1)主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(Slave),数据的复制是单向的,只能由主节点到从节点
(2)默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点
2、主从复制的作用
(1)数据冗余∶主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
(2)故障恢复∶当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复,实际上是一种服务的冗余。
(3)负载均衡∶在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载,尤其是在写
少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量
(4)高可用基石∶除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础
3、主从复制流程
Redis的主从复制功能除了支持一个Master节点对应多个Slave节点的同时进行复制外,还支持Slave节点向其它多个Slave节点进行复制。这样使得我们能够灵活组织业务缓存数据的传播,例如使用多个Slave作为数据读取服务的同时,专门使用一个Slave节点为流式分析工具服务。Redis的主从复制功能分为两种数据同步模式进行:全量数据同步和增量数据同步。
- 建立连接:首先,从服务器会向主服务器发送一个SYNC命令来请求建立连接和同步数据。如果是
初次连接或者之前的复制断开了,主服务器将执行全量复制;否则,它将执行部分复制。 - 快照同步:在进行全量复制时,主服务器会生成RDB(Redis Database)文件,并通过网络传输给
从服务器。接收到RDB文件后,从服务器会清空自己的数据库,并加载新接收到的快照数据。 - 增量同步:完成快照同步后,在进行部分复制时,主服务器将继续记录并缓存所有写操作命令。然
后以类似于日志追加方式(AOF)将这些写操作发送给从服务器进行增量同步。 - 命令重放:当有新命令要被执行时(包括客户端发起写操作),主服务会依次执行该命令并同时发
给所有已经与其建立连接的从服务器。然后每个从服务器都按顺序重放相应的命令来保持数据一致
性。 - 心跳检测和重新连接:为了保持稳定和可靠性,在主从之间还会进行心跳检测。如果从服务器与主
服务器的连接断开,它将尝试重新建立连接并请求同步数据。
主从复制部署
# replicaof <masterip> <masterport>
replicaof 127.0.0.1 6379
#masterauth <password>
#如果主服务器有密码验证,从服务器需要配置主服务器密码
搭建redis主从复制集群,2个集群6台主机
在搭建主从之前在从服务器写一些数据,
测试主从完成后从服务器数据是否存在,
扩展:多主一从,级联主从
192.168.99.121:6379 master1
192.168.99.121:7001 slave1
192.168.99.121:7002 slave2
REPLICAOF 192.168.99.121 6379
192.168.99.121:7003 master2
192.168.99.121:7004 slave3
192.168.99.121:7005 slave4
REPLICAOF 192.168.99.121 7003
级联主从
192.168.99.121:7006 slave of 192.168.99.121:7001
配置定时任务,免交互删除redis中的key
# 安装expect工具,用于自动化交互式应用程序
yum install expect -y
# 创建并编辑一个expect脚本,用于自动删除Redis中的zl键
vim /opt/redis_del_zl.exp
#!/usr/bin/expect
# 启动一个Redis客户端
spawn /usr/local/redis/bin/redis-cli
# 期待看到提示符,表示已成功连接
expect "*>"
# 发送命令删除zl键
send "DEL zl\r"
# 再次期待看到提示符,确保命令已成功执行
expect "*>"
# 发送退出命令,关闭Redis客户端
send "quit\r"
# 允许交互,以便在脚本执行过程中进行手动干预
interact
# 使脚本可执行,以便能够通过cron任务调用
chmod +x
# 编辑crontab,以定时执行删除操作
crontab -e
# 定义一个cron任务,在每天的3点执行删除操作
0 3 * * * /opt/redis_del_zl.exp