序言
单线程的redis为什么这么快?
1.纯内存操作不需要进行磁盘的 IO
2.单线程操作避免了频繁上下文切换
3.采用非阻塞的多路I/O复用模型
什么是路I/O复用模型?
核心是监听socket,压到队列。文件事件分派器快速处理。
假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?
redis是单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了。
三种过期策略
定时删除
惰性删除
定期删除
Redis的内存回收机制
Redis的内存回收主要分为过期删除策略和内存淘汰策略两部分。
1.缓存穿透:查询一个必然不存在的数据。比如文章表,查询一个不存在的id,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成影响。
解决办法:只要从数据库没有查到值,就写一个空值到缓存。
2.缓存失效:如果缓存集中在一段时间内失效,DB的压力凸显。这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。
高并发场景下的缓存+数据库双写不一致问题分析与解决方案设计
解决方案:读写请求串行到一个内存队列中。
分布式锁是啥?对比下redis和zk两种分布式锁的优劣?
利用redis的setnx(key, value):“set if not exits”,若该key-value不存在,则成功加入缓存并且返回1,否则返回0。在有效时间内如果设置成功则获取执行限权,没有那就获取权限失败。
先操作缓存,还是数据库?
读请求:
先读缓存,如果没有命中,读数据库,再set回缓存
写请求:
先缓存,再数据库
缓存,使用delete,而不是set
使用set的情况:第一步成功,第二步失败,会导致,缓存里是set后的数据,数据库里是之前的数据,数据不一致,业务无法接受。
使用delete的情况:第一步成功,第二步失败,会导致,缓存里没有数据,数据库里是之前的数据,数据没有不一致,对业务无影响。只是下一次读取,会多一次cache miss。
什么是跳跃表?
首先先明白数组、链表带来的插入数据的复杂比如:
当数组里存有 1,2,3,4,6,7,8,9,10,11 时,我们向数组内插入5,使用二分查找法快速查找到与3最相近的数字(O(logN)),然后再将其他数字右移(O(N)),那么数组的插入算法的时间复杂度就是O(N)当链表里存有 1,2,3,4,6,7,8,9,10,11时,往链表中插入5,那么就需要逐一比较,时间复杂度为O(N)这样简单的数字看起来插入查询似乎并没有什么性能的影响,但是思考一下,如果此时数据库存在10万条数据,对这个数据进行查询或者插入,是非常耗费性能的。
所以这个时候提出来跳跃表: