admin管理员组文章数量:1794759
Redis面试题整理(二)Redis的线程模型,如何保证Redis中存的是热点数据,数据库和缓存的数据不一致问题
9、Redis的线程模型
Redis内部使用文件事件处理器file event handler,这个文件事件处理器是单线程的,所以Redis才叫单线程的模型。采用IO多路复用机制同时监听多个Socket,根据Socket上的事件来选择对应的事件处理器进行处理。
文件事件处理器的结构包含四个部分:
多个Socket可能会并发的产生不同的操作,因为一个服务器可能会连接多个Socket,每个操作对应的不同的文件事件,但是IO多路复用程序会监听多个Socket,会将Socket产生的时间放入队列中排队,·时间分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
10、布隆过滤器的原理如何在海量的 元素(十亿无序不定长,不重复)中快速判断一个元素存在?
使用传统的数据结构肯定是不行的,为了解决这种问题,引入了位图,它是一个有序的数组,只有0(不存在)、1(存在)。
原理:当一个元素被加入到集合中时,通过k个hash函数将这个元素映射为一个对数组中的k个点,并将他们设置为1,检索时,根据同样的Hash函数查看这些点是否为1,如果这些点中,有任何一个为0,则说明该元素一定不存在,如果都是1,就很可能存在,因为使用Hash函数会产生冲突,查找的点可能是其他元素通过Hash修改的。
可以使用Guava提供的相关类库。
11、Redis和MySQL数据不一致怎么解决?在高并发场景下,因为数据库时用户并发访问的薄弱地方,因此需要使用缓存来做一个缓冲的作用,请求先到达Redis,而读取数据一般没有什么问题,当涉及到数据更新时,就会出现数据库和缓存之间的数据不一致问题。
为了考虑一致性问题,可以考虑更新数据库和缓存或者更新数据库删除缓存。
这两种方式在并发场景下都会出现问题。
为了解决数据不一致问题本质是通过 重试的方式。
解决方案
延时双删:在写库前后都将缓存中的key删除(redis.delKey(key)),并设设定合理的超时时间。
public void write(String key,Object data){ redis.delKey(key); db.updateData(data); Thread.sleep(500); redis.delKey(key); }先删除缓存,在更新数据库,休眠一定的时间,再次删除缓存。
这个休眠一定的时间是根据自己项目的读数据业务逻辑的耗时,以及Redis和数据库的主从同步的耗时来设定的。
休眠是为了保证数据库更新成功,再删除缓存,说到底还是为了保证数据一致性。
缺点:增加了写请求的耗时,在分布式和高并发场景下很难评估具体的延迟时间。
异步重试:把重试请求写到消队列中,有专门的消费者来重试,直到成功,或者直接把操作缓存这一步放在消队列中,有消费者来操作缓存。因为消队列可以保证可靠性以及消可以成功传递。
具体步骤就是当有数据变更时,更新数据库,同时将消存入消队列中有消费者来操作缓存。
订阅数据库变更日志,在操作缓存:在修改数据时,只需要修改数据库,不操作缓存,因为当数据库更新成功后,一定会有binlog日志,然后订阅这个日志,拿到对应的数据,来删除对应的缓存。在订阅变更日志这块,阿里有开元的中间件canal,canal会自动把数据库变更日志投递给下面的消队列。
12、如何保证Redis中存的数据都是热点数据?因为Redis本身有一个内存淘汰策略,在Redis内存数据到一定大小后就会施行内存淘汰策略,可以设置Redis的内存淘汰策略为allkeys-lru,或者allkeys-random淘汰策略等。
13、Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?使用keys指令扫描出指定模式的key列表:keys pre*。但是这个指令会阻塞,因为Redis是单线程的,如果Redis正在线上提供服务,线上服务就会停顿,这时可以使用scan指令,它可以无阻塞的提取出key列表,但有一定的重复概率。
版权声明:本文标题:Redis面试题整理(二)Redis的线程模型,如何保证Redis中存的是热点数据,数据库和缓存的数据不一致问题 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686561403a82081.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论