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作为分布式锁需要考虑的问题:

  1. 存在业务操作异常,未能走到释放锁,锁得不到释放,可能会产生死锁
  2. 使用try catch finally解决上一个问题;除程序抛异常外,程序崩溃,服务器宕机,重启等也可能会导致锁的释放没有执行
  3. 解决上一个问题,需要给锁设置超时时间;另外加锁,设置超时时间可能并不是原子操作,在设置超时时间时,程序崩溃,未能成功设置超时时间也可能导致死锁
  4. 使用lua脚本,或者set原生命令,增加exnx等参数,加锁和设置超时时间在一条命令上执行
  5. 高并发场景下,可能超时时间不合理,A线程业务未处理完 ,锁自动释放,B线程获得锁,开始执行业务,A线程业务执行完释放锁,会把B线程刚加的锁给删掉了,等到B线程业务处理完,释放锁时可能就会出错
  6. 解决上一个问题,就需要加锁时,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更适合用来备份数据库