JAVA面试随笔(redis缓存)

一、为什么使用redis?
            
            优点:1、速度快,基于C语言开发小巧精悍,数据都储存在内存中,使用单线程避免了线程切换的开销以及多线程竞争的问题。
                      2、支持多种数据类型(String,Hash,List,Set,Zset,bitmaps(位图)等)。
                      3、功能丰富,基于发布订阅可实现简单的消息队列,可以设置过期的key。
                      4、支持数据持久化。
                      5、主从复制,能实现高可用的分布式服务。

 二、redis在项目中的使用场景?
            
            1、热点数据缓存。
            2、简单的消息队列。
            3、共享session的服务器。
            4、计数器、限速器(统计在线人数,网站浏览量),排行榜。
        
三、使用redis经常被问到的问题?
            
       1、缓存的并发竞争key的问题?
                
                概述:多个用户操作同时set一个key。
                
                解决方案:
                    1、使用消息队列(消息中间件)将并行请求转为串行请求。
                    2、加锁:在分布式环境中可以使用分布式锁,在业务层操作redis之前,请求一个锁,拿到锁才可以操作(实现锁方                                式:redis,zk)。            
            
       2、缓存的雪崩问题?
                
                概述:redis缓存承载着用户大量的请求,在正常情况下,能有效的保护实际的存储数据库(如mysql数据库),但是如果                  由于redis缓存大量失效或者redis缓存服务器突然断电或者宕机原因整体停止服务,则导致大量的用户请求直接访问数据                     库,可能瞬间就把数据库压垮,从而造成雪崩问题。
                
                解决方案:
                    1、优化缓存的过期时间:设计好redis的key的过期时间,避免缓存在同一时间同时失效。
                    2、设置redis的key不过期:如果有足够大的内存可以设置key不过期。
                    3、保持redis的高可用性:搭建redis集群,防止缓存大面积失效,即使有节点失效,其他节点也可以正常工作。
                    4、使用缓存降级:虽然也有缺陷,但能保证核心功能的运作。
                    5、及时备份redis,快速预热数据。
            
       3、如何尽量保证缓存存储的都是热点数据的问题?
                
                解决方案:
                    根据热点数据量,来限定redis的内存存储,再使用redis的自身支持的淘汰策略(6种):
                    allkeys-lru: 在所有key中优先删除最近最少使用(less recently used ,LRU) 的 key。
                    volatile-lru: 在设置了超时时间(expire )的key中优先删除最近最少使用(less recently used ,LRU) 的 key。
                    
            
       4、缓存与数据库双写不一致的问题?
                
                解决方案:每个方案都不是绝对的,我们当时使用的是‘先删除缓存,在更新数据库’。这样也会有问题可以使用延时删                   除方式,先删除缓存, 在更新数据库,更新完数据库,线程停一下(时间根据项目需要来定),然后在删除一次缓存。
                    
            
      5、缓存的穿透问题?
                
                概述:客户端查询一条不存在数据,缓存中没有这条数据,然后就去数据库中查询,数据库里也没有这条数据,在高并发                   的环境下,对数据库造成很大的压力 ,甚至会打垮数据库。
                
                解决方案:在缓存中缓存空对象,在查询完数据库后如果没有该数据,就缓存一个空的数据到redis中,再有访问该条数据                  请求时,直接在 缓存中获取,如果该条数据在数据库中添加了,就马上替换掉redis缓存的空值,当然这种方法也有缺                        点,就是redis存储了大量的 空值,所以我们要把空值的过期时间根据项目的需求适当的调小。
            
     6、Redis与Memcache的区别都有哪些?
                    
                首先来说redis与memcache缓存在项目的某些场景下各有各的好处,并且都能提升程序的性能,redis是mencache缓存                     在性能上的提升。
                
                区别:
                    1、支持的数据类型:
                        redis数据类型丰富,不仅是k/v数据类型,还支持hsah,set list等类型
                        memcache支持简单数据类型,memcache可以缓存一些图片或者是视频,需要客户端自己处理
                        redis支持的数据类型比memcache支持的多。
                    2、存储方式持久化:
                        redis有自身的持久化的方案可以将数据落地到硬盘上,
                        mamcache数据没有持久化的方案,只保存在内存中一旦断电数据就会丢失。
                    3、分布式操作:
                        redis支持master-slave复制模式
                        memcache可以使用一致性hash做分布式
                    4、数据一致性操作:
                        redis使用的是单线程模型,保证了数据按顺序提交。
                        memcache需要使用cas保证数据一致性。
            
    7、redis的缓存击穿问题?
                    
                概述:缓存中有的热点数据,在缓存中丢失时,大量的请求打到数据库上,压垮数据库,使数据库瞬间瘫痪,比如商                      品的 秒杀或抢购的环境。

                解决方案:
                    
                    1、加锁排队机制:如果缓存中没有这条数据,则将请求锁上,然后缓存从数据库中加载到数据时再释放锁,其他请                           求没有得到锁就排队等待,可以先返回一个排队中的提示,注意:如果项目使用分布式要使用分布式锁。
                          这种方式会使程序的响应时间增加,进而降低其吞吐量。
                    
                    2、使用布隆过滤器(用于快速判某个元素是否存在于集合中,不存在就直接返回)。

猜你喜欢

转载自blog.csdn.net/qq_42891281/article/details/105253506