持久化机制
RDB快照<br>
生成方式
自动触发:每次到备份时间就会fork一个子线程生成dump.rdb文件
手动触发
save<br>
bgsave - 后台生成
flushall<br>
shutdown
优点
生成快照不影响主流程
文件紧凑,节省空间
恢复速度快<br>
可以定时备份rdb文件,作为冷备<br>
不足
不能实时持久化,宕机恢复后可能会缺少几分钟的数据
AOF日志
启用
在redis.conf中配置appendonly on
优点
每秒写入日志,宕机恢复最多损失一秒的数据
日志文件的可读性高,并且可以自由修改,在恢复redis时可以从AOF日志中删除一些致命的指令,如flash all
文件压缩
手动压缩
aof文件中记录的是每个指令,当文件膨胀到一定程度的时候,可以使用压缩指令,将redis中现存的key重写一份到AOF中<br>
自动压缩
除了手动压缩外,redis也会自动压缩AOF,触发条件为AOF大小为上一次大小的两倍且文件大于64M<br>
文件压缩时有新命令怎么办?
会将新的命令先放入缓冲区中,等压缩完成后再写入aof
生产环境选择哪一个
redis默认是使用RDB,可以将两种都开启<br>
基础
什么是redis
redis是一种基于内存,使用键值对存储的非关系型数据库
为什么要使用redis
高性能:将一些在数据库查询相对较慢的数据缓存到redis中,可以获得更快的查询速度<br>
高并发:在并发环境下,大量的请求直接发送的数据库,数据库可能承受不了大量的访问压力。使用redis可以在并发环境下保护数据库
为什么不用HashMap(guava实现的缓存)
生命周期角度:本地缓存的生命周期随JVM关闭而结束,Redis中的缓存理论上是可以一直存在的
分布式角度:本地缓存的作为范围在当前JVM中,而Redis作为分布式缓存可作用在多个服务中
为什么不用Memcached<br>
Redis支持更多的数据结构
Redis功能更加丰富,支持持久化、事务、lua脚本、pipeline等<br>
Redis自带分布式高可用的实现,sentinel或cluster
redis有多快
可以达到10万QPS
使用redis-benchmark性能测试工具可以测试QPS
使用redis-benchmark性能测试工具可以测试QPS
redis为什么快
完全基于内存操作,并使用Hash表格式做存储
redis请求单线程,避免创建、关闭线程、上下文切换带来的性能消耗(CPU不是redis的性能瓶颈,单核就已经够用了)
使用同步非阻塞的多路复用模型,多个socket共用一个线程
数据类型
String
存储格式:key-vlaue
存储类型:int , float , String
应用场景
数据库缓存
分布式数据共享,如session、token
计数器
生成全局唯一id
分布式锁
限流
Hash
存储格式:key-field-value
存储类型:键值对
应用场景<br>
String格式能做的,Hash都能做(redisson使用hash类型实现的分布式锁)
用键值对存储对象
购物车
key - 用户id , field - 商品id ,value - 商品数量<br>
Set
存储格式:key-无序集合
应用场景
抽奖(spop弹出)
点赞、签到、打卡(不重复特性)<br>
共同好友、条件筛选(交集)
Zset(Sorted Set)
存储格式:key-score-member<br>
其它
Hyperloglogs
基于基数的统计,比如网站访问量,日活、月活,uvpv
高级功能
发布/订阅 pub/sub
使用pubulish发布消息,subscribe订阅消息<br>
在redis集群中会用到发布订阅功能,但是实际业务中还是建议使用专业的消息队列
事务
命令
muti - 开启事务
exec - 执行事务
discard - 取消事务<br>
watch - 监视
类似乐观锁:监视一个key的变化,如果事务运行时,被监视的key已经改变,则事务执行失败
特点
事务不能嵌套,使用多个muti的效果是一样的
开启事务后,每个redis指令都会放入的队列中,执行exec时按顺序执行
redis的事务不会回滚,某个指令错误后,之前已经执行的指令不会回滚到之前的值
Lua脚本
特点<br>
一个脚本中可以有多个操作,并将这些操作组合成一个原子性的整体来执行
可以将脚本写在文件中,作为一个指令组来重复执行
Lua脚本在执行时,会阻塞其他客户端的请求
常用语法
在客户端用使用 eval 执行脚本
脚本中调用redis的操作<br>
"redis.call('command','key','value')"<br>
如果有返回值在redis.call前边加上return
如何对脚本传参
eval "return redis.call('command',KEYS[1],ARGV[1]) 参数个数 实参key 实参value"<br>
脚本超时
如果脚本中没有对key做操作,使用script kill 干掉脚本
如果脚本中对key有更新,就杀不掉了,只能强制停止服务,shutdown nosave
摘要
可以将Lua脚本生成摘要来使用,使用 script load
使用evalsha可以通过摘要来执行脚本