美文网首页
redis MS题总结

redis MS题总结

作者: hehehehe | 来源:发表于2022-12-23 10:08 被阅读0次

    https://blog.csdn.net/m0_58479954/article/details/124790349

    Redis支持的数据类型有哪些?

    • 字符串
    • hash
    • list
    • set
    • zset

    Redis为什么是单线程的

    • 代码更清晰,处理逻辑更简单;
    • 不用考虑各种锁的问题,不存在加锁和释放锁的操作,没有因为可能出现死锁 而导致的性能问题;
    • 不存在多线程切换而消耗CPU;
    • 无法发挥多核CPU的优势,但可以采用多开几个Redis实例来完善

    Redis真的是单线程的吗?

    • Redis6.0之前是单线程的,Redis6.0之后开始支持多线程;
    • redis内部使用了基于epoll的多路服用,也可以多部署几个redis服务器解决单线程的问题;
    • redis主要的性能瓶颈是内存和网络;
      内存好说,加内存条就行了,而网络才是大麻烦,所以redis6内存好说,加内存条就行了;
      而网络才是大麻烦,所以redis6.0引入了多线程的概念,
      redis6.0在网络IO处理方面引入了多线程,如网络数据的读写和协议解析等,需要注意的是,执行命令的核心模块还是单线程的。

    Redis持久化有几种方式?

    分别是RDB(Redis DataBase)和AOF(Append Only File)

    • RDB,简而言之,就是在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上;
    • AOF,则是换了一个角度来实现持久化,那就是将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。

    什么是缓存穿透?怎么解决?

    1、缓存穿透
    一般的缓存系统,都是按照key去缓存查询,如果不存在对用的value,就应该去后端系统查找(比如DB数据库)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

    2、怎么解决?
    对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert之后清理缓存。

    对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该Bitmap过滤。

    缓存雪崩

    当缓存服务器重启或者大量缓存集中在某一时间段失效,这样在失效的时候,会给后端系统带来很大的压力,导致系统崩溃。

    如何解决?

    • 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其它线程等待;
    • 做二级缓存;
    • 不同的key,设置不同的过期时间,让缓存失效的时间尽量均匀;

    缓存击穿:

    指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。

    怎么保证缓存和数据库数据的一致性?

    1、淘汰缓存
    数据如果为较为复杂的数据时,进行缓存的更新操作就会变得异常复杂,因此一般推荐选择淘汰缓存,而不是更新缓存。

    2、选择先淘汰缓存,再更新数据库
    假如先更新数据库,再淘汰缓存,如果淘汰缓存失败,那么后面的请求都会得到脏数据,直至缓存过期。
    假如先淘汰缓存再更新数据库,如果更新数据库失败,只会产生一次缓存穿透,相比较而言,后者对业务则没有本质上的影响。

    3、延时双删策略

    延时双删策略

    1、什么是延迟双删?
    延迟双删策略是分布式系统中数据库存储和缓存数据保持一致性的常用策略,但它不是强一致。其实不管哪种方案,都避免不了Redis存在脏数据的问题,只能减轻这个问题,要想彻底解决,得要用到同步锁和对应的业务逻辑层面解决。

    2、为什么要进行延迟双删?
    一般我们在更新数据库数据时,需要同步redis中缓存的数据,所以存在两种方法:
    * 第一种方案:先执行update操作,再执行缓存清除。
    * 第二种方案:先执行缓存清除,再执行update操作。

    这两种方案的弊端是当存在并发请求时,很容易出现以下问题:
    * 第一种方案:当请求1执行update操作后,还未来得及进行缓存清除,此时请求2查询到并使用了redis中的旧数据。
    * 第二种方案:当请求1执行清除缓存后,还未进行update操作,此时请求2进行查询到了旧数据并写入了redis。

    3、如何实现延迟双删?
    所以此时我们需要使用第三种方案:先进行缓存清除,再执行update,最后(延迟N秒)再执行缓存清除。
    4、需要注意的点
    上述中(延迟N秒)的时间要大于一次写操作的时间,一般为3-5秒。
    原因:如果延迟时间小于写入redis的时间,会导致请求1清除了缓存,但是请求2缓存还未写入的尴尬。。。
    ps:一般写入的时间会远小于5秒

    5、小结

    • 延迟双删用比较简洁的方式实现 mysql 和 redis 数据最终一致性,但它不是强一致。
    • 延迟,是因为 mysql 和 redis 主从节点数据同步不是实时的,所以需要等待一段时间,去增强它们的数据一致性。
    • 延迟是指当前请求逻辑处理延时,而不是当前线程或进程睡眠延迟。
    • mysql 和 redis 数据一致性是一个复杂的课题,通常是多种策略同时使用,例如:延迟双删、redis 过期淘汰、通过路由策略串行处理同类型数据、分布式锁等等。

    Redis分布式锁有什么缺陷?

    redis命令:set users 10 nx ex 12 原子性命令
    Redis 分布式锁不能解决超时的问题,分布式锁有一个超时时间,程序的执行如果超出了锁的超时时间就会出现问题。

    Redis 过期策略和内存淘汰策略

    Redis的过期策略

    我们在set key的时候,可以给它设置一个过期时间,比如expire key 60。指定这key60s后过期,60s后,redis是如何处理的嘛?我们先来介绍几种过期策略:

    • 定时过期
      每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即对key进行清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
    • 惰性过期
      只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
    • 定期过期
      每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
      expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。
    Redis 内存淘汰策略

    redis的key被大量使用,内存直接不够了,运维小哥哥也忘记加大内存了。难道redis直接这样挂掉?不会的!Redis用8种内存淘汰策略保护自己~
    LRU:最近最少使用(最长时间)淘汰算法(Least Recently Used)。LRU是淘汰最长时间没有被使用的页面。
    LFU:最不经常使用(最少次)淘汰算法(Least Frequently Used)。LFU是淘汰一段时间内,使用次数最少的页面。

    • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的key中,根据过期时间进行淘汰,越早过期的优先被淘汰;

    • volatile-lru:当内存不足以容纳新写入数据时,从设置了过期时间的key中使用LRU(最近最少使用)算法进行淘汰;

    • volatile-lfu:4.0版本新增,当内存不足以容纳新写入数据时,在过期的key中,使用LFU算法进行删除key。

    • volatile-random:当内存不足以容纳新写入数据时,从设置了过期时间的key中,随机淘汰数据;。

    • allkeys-lru:当内存不足以容纳新写入数据时,从所有key中使用LRU(最近最少使用)算法进行淘汰。

    • allkeys-lfu:4.0版本新增,当内存不足以容纳新写入数据时,从所有key中使用LFU算法进行淘汰;

    • allkeys-random:当内存不足以容纳新写入数据时,从所有key中随机淘汰数据。

    • noeviction:默认策略,当内存不足以容纳新写入数据时,新写入操作会报错。

    Redis的跳跃表

    • 跳跃表是有序集合zset的底层实现之一
    • 跳跃表支持平均O(logN),最坏 O(N)复杂度的节点查找,还可以通过顺序性操作批量处理节点。
    • 跳跃表实现由zskiplist和zskiplistNode两个结构组成,其中zskiplist用于保存跳跃表信息(如表头节点、表尾节点、长度),而zskiplistNode则用于表示跳跃表节点。
    • 跳跃表就是在链表的基础上,增加多级索引提升查找效率。

    Redis 事务机制

    Redis通过MULTI、EXEC、WATCH等一组命令集合,来实现事务机制。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
    简言之,Redis事务就是顺序性、一次性、排他性的执行一个队列中的一系列命令。

    Redis执行事务的流程如下:
    开始事务(MULTI)
    命令入队
    执行事务(EXEC)、撤销事务(DISCARD )

    在生成 RDB期间,Redis 可以同时处理写请求么?

    可以的,Redis提供两个指令生成RDB,分别是save和bgsave。

    如果是save指令,会阻塞,因为是主线程执行的。
    如果是bgsave指令,是fork一个子进程来写入RDB文件的,快照持久化完全交给子进程来处理,父进程则可以继续处理客户端的请求。

    一个字符串类型的值能存储最大容量是多少?

    512M。

    单线程的redis为什么这么快?

    (一)纯内存操作
    (二)单线程操作,避免了频繁的上下文切换
    (三)采用了非阻塞I/O多路复用机制

    Redis的内存用完了会发生什么?

    如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以将Redis当缓存来使用配置淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。

    MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?

    Redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。

    假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?

    使用 keys 指令可以扫出指定模式的 key 列表。 对方接着追问:如果这个 redis 正在给线上的业务提供服务,那使用 keys 指令会有什么问题?

    这个时候你要回答redis关键的一个特性:redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。

    如果有大量的key需要设置同一时间过期,一般需要注意什么?

    如果大量的key过期时间设置的过于集中,到过期的那个时间点,redis可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。

    Redis集群如何选择数据库?

    Redis集群目前无法做数据库选择,默认在0数据库。

    Redis集群会有写操作丢失吗?为什么?

    Redis并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。

    说说Redis哈希槽的概念?

    Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384 取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

    Redis的同步机制了解么?

    Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

    相关文章

      网友评论

          本文标题:redis MS题总结

          本文链接:https://www.haomeiwen.com/subject/czpbqdtx.html