Redis知识梳理
文章目录
- 前言
- Redis是什么
- Redis使用场景
- Redis支持的数据结构
- Redis应用
- 分布式锁
- 实现异步队列
- 同步机制 (主从复制)
- 哨兵机制(:hearts:)
- 持久化
- 总结
前言
Redis是什么
开源的,内存中的数据结构存储系统。
基于内存又可持久化、key-value数据库。
可以用作数据库、缓存和消息中间件。
Redis使用场景
- 缓存
- 消息队列
- 分布式锁
Redis支持的数据结构
- String
- list
- hash
- set
- sortedset
Redis应用
分布式锁
实现思想:使用setnx命令加锁,并使用expire给锁加一个超时时间,超过该时间,则自动释放锁;锁的value值为随机生成的id,释放锁时要判断下,是不是该锁。
1)使用set命令缓存锁
set key value nx ex time
2)使用lua脚本设置
if redis.call('setNx',KEYS[1],ARGV[1]) then if redis.call('get', KEYS[1])==ARGV[1] then return redis.call('expire', KEYS[1], ARGV[2]) else return 0 end end
if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end
程序中使用redis
作为分布式锁需要考虑的问题:
- 存在业务操作异常,未能走到释放锁,锁得不到释放,可能会产生死锁
- 使用
try catch finally
解决上一个问题;除程序抛异常外,程序崩溃,服务器宕机,重启等也可能会导致锁的释放没有执行 - 解决上一个问题,需要给锁设置超时时间;另外加锁,设置超时时间可能并不是原子操作,在设置超时时间时,程序崩溃,未能成功设置超时时间也可能导致死锁
- 使用
lua
脚本,或者set
原生命令,增加ex
,nx
等参数,加锁和设置超时时间在一条命令上执行 - 高并发场景下,可能超时时间不合理,A线程业务未处理完 ,锁自动释放,B线程获得锁,开始执行业务,A线程业务执行完释放锁,会把B线程刚加的锁给删掉了,等到B线程业务处理完,释放锁时可能就会出错
- 解决上一个问题,就需要加锁时,value值设置为唯一值,释放锁时,通过这个唯一id,判断是不是该锁;超时时间的设置,在加锁成功后,启动一个守护线程,守护线程每隔三分之一超时时间就去延迟锁的超时时间(续命),业务处理完,要关闭守护线程
实现异步队列
用List
结构作为队列,rpush
生产消息,lpop
消费消息
同步机制 (主从复制)
配置:
slaveof <masterip> <masterport>
哨兵机制(♥️)
- 解决主从复制的缺点
- 当主节点出现故障,由
Redis sentinel
自动完成故障发现和转移,实现高可用
持久化
-
RDB
快照
rdb:在恢复时将rdb文件读到内存
备份如何进行:fork子进程(Linux系统写时复制技术),数据写入rdb文件,要考虑数据是否庞大;
数据恢复:大规模数据的恢复,rdb 比 aof 更加高效,且节省磁盘空间;缺点就是,数据的完整性得不到保证,rdb可能会丢失最后一次没来得及持久化的数据;
##rdb配置相关
#时间策略
save 900 1
save 300 10
save 60 10000
#文件名称
dbfilename dump.rdb
#文件保存路径
dir ./
#如果持久化出错,主进程停止写入
stop-writes-on-bgsave-error yes
# 是否对RDB文件进行压缩,默认是yes
rdbcompression yes
#是否对rdb文件进行校验,默认是yes
rdbchecksum yes
AOF
aof:写命令–》aof缓冲区–》aof磁盘文件
备份:日志形式追加增量记录,记录的redis执行的写指令
数据恢复:redis重启时会读取aof文件重新构建数据,重新执行了一遍指令,速度较慢,完整性较好;
##aof配置相关
#是否开启AOF
appendonly no
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
#三种同步策略
#每次接受到写命令,强制写入磁盘
# appendfsync always
#每秒写入一次
appendfsync everysec
#完全依赖操作系统写入
# appendfsync no
#在日志重写时,不进行命令追加操作,而是将其放到缓冲区里,避免与命令的追加造成DISK IO的冲突
no-appendfsync-on-rewrite no
#当前AOF文件是上次日志重写得到AOF文件大小的两倍时,自动启动新的日志重写过程
auto-aof-rewrite-percentage 100
#当前AOF文件启动新的日志重写过程的最小值,避免频繁重写
auto-aof-rewrite-min-size 64mb
#加载aof时如果有错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
总结
-
rdb
可以再指定的时间间隔对数据进行快照存储 -
aof
记录执行的写命令,追加到文件末尾,在重启时会重新执行来恢复原始数据 - 可对
aof
文件进行重写,让文件不至于过大 - 比较稳妥的做法是同时开启两种持久化方式,当
redis
重启的时候,会优先加载aof
文件来恢复原始数据,aof
保存的数据要比rdb
完整 -
rdb
更适合用来备份数据库