浅谈redis
一种分布式内存数据库,相当于一套运行在内存里面的某种通用存储模块(NoSQL,即不需要SQL语句的数据库)
因为在内存之中,所以不需要sql需要通过非常复杂的方法才可以实现高效搜索,底层维持单线程,同时也可以进行一些相对比较复杂的操作和使用相对比较复杂的数据模型(例如管道命令应对抢购秒杀问题);同时事务处理和复杂联表查询功能缺失
数据本质上存储在一个map里面,里面的value却又支持各种数据类型,也可以对此数据结构有相对复杂的操作,例如链表左右push、pop等操作
内部以16383个哈希槽存储数据,利用CRC16计算出code再取余,同时可以使用主从复制实现集群,进行读写分离、分片工作、主从切换(配置单数哨兵服务器集群)
值得一提的是(有待勘误)
关系型数据库(例如mysql)主从分离进行的是master增删改,slave从查
非关系型数据库(例如redis)主从分离进行的是master增删改查,slave从查;尤其是redis3集群甚至是主从平等
也许是性能差异,非关系型内存占用多,性能普遍大,可以承担起更多的工作
特性
单线程(实际上加的是分布式的锁),可以通过单个服务器开启一个集群,单个集群中包含多个节点提高效率
支持数据库落地,拥有故障恢复模式(RDB和AOF)
支持类型丰富: String、hash(map)、list、set、zset
缓存空间:String 512m 、hash 232
比较流行value的存放序列化方式为protobuf,除开肉眼不可读以外(结构数据化),几乎没有其他缺点(数据序列化:跨语言多平台、高效、拓展兼容性好)。
key一般为String
使用场景
- 需要高频率的读取
- 不大关注数据的一致性、及时性
- 对数据的修改请求比较少
缓存穿透
黑客故意去请求缓存中不存在的数据,导致所有的请求都积压到数据库中
解决方案
利用互斥锁,没得到锁就休眠一定时间,缓存失效时先去获得锁再请求数据库
采用异步更新策略,无论key值是否取到值,都直接返回。
value值中维护一个失效时间,如果缓存过期,异步起一个线程去读数据库
需要缓存预热(项目启动先加载缓存)操作
布隆过滤器,内部维护一系列合法的key,如果收到不合法的key,直接返回
雪崩问题
缓存同时间大面积失效(setKey的时候设置的过期时间),同时收到一大波请求直接访问数据库,引起数据库异常
解决方案
缓存失效时间设置随机值
使用互斥锁(会引起性能下降)
双缓存 A和B
- 缓存A设置失效时间为20min,缓存B不设置失效时间
- 实现过程中先从A读取数据,有则直接返回
- 没有则从B读取数据,直接返回,同时异步开启一个更新线程,更新线程同时更新缓存A和缓存B
混合持久化(数据恢复)
redis内部也有持久化方案,,可以将当前redis内存内部的数据保存到硬盘上,也属于一种数据保险 ,数据恢复策略
对比mongodb,属于实实在在的数据落盘,往往会给以redis持久化的补充
具有两种策略
RGD:(Redis Database backup) 数据库快照
将当前所有数据转换成二进制对象,且保存再硬盘上,默认生成dump.rdb文件
在断电时回复上一次的信息
配置文件 修改信息:
save 60 5 (一分钟内有5个key被修改即使用快照)
AOF
保存运行的命令日志,理论上可以断电回复所有数据
但是高频率IO过于影响性能,往往采取一定时间保存一次日志,进行一次IO(比如1min)
支持
AOf rewrite
: 删除冗余的指令日志配置文件 修改信息:
appendonly yes