AOF append only file
记录命令,而非数据
后写日志,不阻塞当前操作,但阻塞下次操作,主线程写回磁盘文件,有可能丢最后一条命令日志
写回策略
always(同步/高可靠/对性能有一定影响) 每条命令立刻写回磁盘
everysec(推荐使用) 先存在内存缓冲区 每秒写一次到磁盘
no(高性能) 由操作系统决定什么时候从缓冲区到磁盘文件
AOF文件过大问题
AOF重写,将操作同一个数据的多条命令缩减为一条以减少文件大小
主线程fork一个子进程,同时备份一份最新的数据在内存,然后该进程根据该份数据进行重写日志编写(只记录数据的写入操作,就比记录全部命令小很多)
同时,主线程还是正常写入AOF日志,并且记录拷贝数据之后的写入记录到AOF重写日志
上面两个步骤结合,就能保证最新的(主线程保证)最全的(子进程+主线程保证)写入记录是有的,且没有多余的操作记录,然后用重写日志替换(写会磁盘时做)原有全部操作记录的AOF日志就达到了减少AOF体积的目的
RDB RedisDataBase 内存快照
采用全量数据的快照
bgsave 默认,fork出子进程执行快照操作不阻塞主线程
save 阻塞方式
使用写时复制(Copy-on-write COW),解决子线程做快照时主线程不能执行写操作(此时执行写会破坏快照的正确性)的问题
做快照的过程中,如果主线程有写入操作,先行拷贝原值供子进程做快照,主线程照常执行
为了解决,快照间隔过短(时间足够短才能降低丢失数据)加之全量数据过大导致的,
1. 频繁fork导致主线程性能下降
在适当长时间的做快照
2. 连续写磁盘压力过大问题。
两次 快照之间只为修改了的数据(使用多余的1/4空间记录修改)做快照,但因该多余的修改记录带来了内存开销
Redis 4.0 提出 RDB AOF混合,两次快照之间的数据修改使用AOF记录(如果此中间宕机了可以使用AOF,且非全量数据的AOF避免了重写机制的开销),
快照方式依然是全量(RDB保证了恢复的效率)
数据结构
数据类型
String Hash Set SortedSet List
底层数据结构
动态字符串 双向链表 压缩列表 跳表 hash表 整数数组
全局使用 hash表查询 key
使用两个全局hash表,渐进式rehash进行扩容
使用拉链法解决hash冲突
开放定址法(线性探索法)遇到冲突,顺序向数组末尾继续查找直到有空位填充
缓存一致性问题
Redis中有,数据库必须一致。Redis中没有,数据库必须是最新的。
Redis的作用分为:
读写缓存(对redis执行读和增删改操作)
同步直写(事务操作,写入Redis同个事务写入DB),采用此法即可
异步写回(删Redis才会写回DB,若此时Redis故障,出现不一致)
只读缓存(只会读,没读到从DB加载,增删改直操DB并标记Redis过期)
新增数据,直写DB无一致性问题
删改,因不保证操作DB和Redis是同事务,加上并发情况,出现不一致
1、因DB和Redis两步操作有失败出现不一致,使用消息队列等重试机制
2、因两步操作并发导致出现不一致,使用延时双删(DB完成后, sleep另一个线程的操作时间再删一次redis)
缓存雪崩 (大量崩溃)
大量数据同时过期导致,数据库压力剧增
过期时间加随机
暂停服务等待恢复,核心继续走库,服务降级
缓存击穿(热点被打穿了)
部分数据(热点数据),被并发访问,数据库压力剧增
热点不过期
缓存穿透(直接穿过了)
大量请求获取redis和数据库都不存在的数据,库压力剧增
类似恶意请求,解决办法
布隆过滤器(3个hash函数+bit数组)
经过函数计算得到的三个位置不是全部为true,则数据不存在
前端过滤,幂等性接口
锁
原子操作的实现
- INCR 原子加1,DNCR 原子减1单命令,复杂情况下不可用
Lua脚本,多命令原子执行
// eval 执行, args参数
redis-cli —eval lua.script keys , args
分布式锁实现
单命令实现
// setnx 存在key则不做操作,没有则创建并设为value
SETNX lock_key value
DEL lock_key
为防止出现有客户端出现不 DEL锁的情况,加入过期时间。防止出现误释放,value设为唯一标识
SET lock_key unique_value NX PX 1000
DEL时使用Lua脚本来判断是否是本客户端加的锁,是则可释放
高可靠多节点锁 RedLock
多个节点,有半数以上节点加锁成功则认为加锁成功,否则失败,如此即使有个别节点有问题还有其他节点提供锁支持
步骤:
客户端记录加锁开始时间
向N个Redis节点 发起加锁命令(key, unique_value,过期时间)
客户端接收返回并判断
加锁耗时是否超过了过期时间,业务操作耗时是否会大于过期时间
有N/2个节点加锁成功,否 开始释放锁操作
客户端使用Lua脚本向N个实例发送释放操作
印象笔记,让记忆永存。 下载印象笔记 |
---|