总结各路大神的redis知识

本文详细介绍了Redis的特点,包括其高性能缓存机制、数据类型及其应用场景、过期策略与内存淘汰机制等。此外,还探讨了Redis在解决缓存一致性、并发竞争等问题上的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、https://blog.youkuaiyun.com/hjm4702192/article/details/80518856如老师一般的讲解:

Redis

一、基础:

  • Redis选择
    • 性能:缓存,读取速度快。
    • 并发:频繁访问数据库会导致连接异常,redis作为缓冲,可以使得请求先访问redis,而不是直接访问数据库。
  • https://i-blog.csdnimg.cn/blog_migrate/fd9850536f269f0092e9b3d39c0885cf.jpeg

 

  • redis缺点:
    • 缓存与数据库双写一致性问题
    • 缓存雪崩 问题
    • 缓存击穿问题
    • 缓存的并发竞争问题
  • redis单线程为什么快:
    • 纯内存操作
    • 单线程操作,避免频繁切换上下文
    • 采用了非阻塞I/O多路复用机制(队列,redis还提供了select ,epoll,evport,kqueue等多路复用函数库)

https://i-blog.csdnimg.cn/blog_migrate/2928c2095ded51a5fc540c33392880c2.jpeg

 

  • redis数据类型及使用场景:
    • String(get、set操作,value可以是String也可以是数字,一般做一些复杂的计数功能的缓存)
    • Hash(value存储的是结构化的对象,比较方便的就是操作其中的某个字段。)
    • set(因为set堆放的是一堆不重复值的集合,所以可以做全局去重的功能,不适用JVM自带的set是因为系统一般是集群部署,使用jvm自带的set比较麻烦,为了一个全局去重,再起一个公共服务太麻烦;还有就是利用交并差集等操作可计算共同喜好,全部喜好和自己独有的喜好等功能)
    • list(使用list的数据结构可以做简单的消息队列功能。还可以利用lrange命令做基于redis的分页功能,性能极佳,用户体验好,生产着消费者场景,list可很好的完成排队,先进先出的原则)
    • sorted set(多了一个权重score,集合中的元素能够按score进行排列,可以做排行榜应用,取topN操作)
  • redis过期策略和内存淘汰机制
    • 分析问题角度是:存10G但是内存只有5G需要删除5G的内存,怎么删除,数据已经设置过过期时间,但是到期内存占比依然很高是怎么回事
    • redis采用的是定期删除+惰性删除策略。
    • 不用定时删除的原因是,定是删除就是用一个定时器监视key,过期则自动删除,虽然内存及时释放了,但是十分消耗CPU资源,在大并发请求下,CPU要将时间应用在处理请就上,而不是删除可以,所以没有采用这一策略。
    • 定期删除+惰性删除的工作模式:定期删除:redis每隔100ms检查,是否有过期的可以,有则删除,并且采取的是随机抽取。如果只采用定期删除策略,会导致很多可以到期没有删除,所以会有惰性删除派上用场,在获取某个可以的时候,redis会检查,这个key如果设置了过期时间那么是够过期了,如果过期了就会删除。
    • 问题:如果定期删除没有删除可以,也没有即使请求可以,也局势说惰性喊出没有生效,这样redis的内存会越来越高,那么就应该采用内存淘汰机制。
    • redis.conf文件中有一行配置,#maxmemory-policyvolatile-lru该配置就是配内存淘汰策略的。
      • noeviction(不推荐):当内存不足以容纳写入数据时,新写入操作会报错。
      • allkeys-lru:但内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
      • allkeys-random(不推荐):但内存不足以容纳新写入数据时,在键空间中,随机移除某个key
      • volatile-random(不推荐):但内存不足以容纳新写入的数据时,在设置了过期时间的键空间中,随机移除某个key
      • volatile-lru(不推荐):但内存不足以容纳新写入的数据时,在设置了过期时间的键空间中,一处最近最少使用的key,这种情况一般是把redis既当缓存又做吃牛华存储的时候才用。
      • volatile-ttl(不推荐):当内存不足以容纳新写入的数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
      • 如果没有设置expire的key不满足prerequisites,那么volitile-*和noeviction基本上一致。
  • redis和数据库双一致性问题:
    • 一致性问题是分布式常见问题,还可以再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。如果对数据有强一致性要求,则不能放缓存。所做的一切只能保证最终一致性。从根本上来说智能降低不一致发生的概率,无法完全避免,因此,有强一致要求的数据不能放缓存。
      • 采取正确更新策略;
      • 先更新数据库
      • 再删除缓存;
      • 因为可能存在删除缓存失败的问题,同一个补偿措施即可,例如利用消息队列。
  • 缓存穿透和雪崩应对策略:
    • 缓存穿透:黑客故意去请求不在缓存中的数据,导致酥油的请求都堆到数据库上,从而使得数据库连接异常。
      • 解决方案:利用互斥锁,缓存失效的时候先去获得锁,得到锁了,再去请求数据库,没有得到锁,则休眠一段时间重试。
      • 采用异步更新策略,无论key是否取到值,都直接返回。Value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,现价在缓存)操作。
      • 提供一个能迅速判断请求是狗有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的可以,迅速判断出,请求所携带的key是否合法有效。如果不合法,则直接返回。
    • 缓存雪崩:即为缓存在同一时间内大面积失效,这个时候又来了一波请求,结果请求都堆到数据库上,从而导致数据库连接异常。
      • 给缓存的失效时间加一个随机值,避免集体失效。
      • 使用互斥锁,但是该方案吞吐量明显下降了。
      • 双缓存,设两个缓存,AB,缓存A的失效时间为20分钟,缓存B不设失效时间。自己租缓存预热操作,然后
        • 从A读数据库,有则直接返回。
        • A没有直接从B读,直接返回,并且一步启动一个更新线程。
        • 更新线程同时更新缓存A、B
  • redis并发竞争问题如何解决:
    • 如果对这个key操作,不要求顺序,则准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可。
    • 如果有顺序要求,则对于每个系统获取key的时候都设置一个时间戳,保证顺序一致性,
    • 利用队列,穿行访问。

 

二、一些零散redis知识:

  • redis是非关系型数据库;mysql是关系型数据库,oracle,db2,也是。
  • redis中的数据版存储在内存中,持久化,这是它速度极快的原因;mysql中的数据存储在本地磁盘中,会进行持久化。
  • redis实现分布式锁的命令:set(key,value,NX,EX,expiretime);
  • redis和memcachned的区别:
  • 性能对比:redis只使用单核,memcached使用多核,所以平均每一个核上redis在存储小数据时比memcached性能更高。而在100k以上的数据中,memcached性能要高于redis,虽然redis最近也在存储大数据的性能上进行优化,但是比起memcached的还是稍有逊色。
  • 内存使用效率对比:使用简单的key-value存储的话,memcached的内存利用率更高,而如果redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于memcached。另外,memcached使用预分配的内存池的方式,带来一定程度的空间浪费,并且在内存仍然很大空间时,新的数据也可能会被剔除,而redis使用现场申请内存的方式来存储数据,不会剔除任何非临时数据,Redis更适合作为存储而不是cache。
  • redis支持服务器端的数据操作;redis相比memcached来说,拥有更多的数据结构和支持更丰富的数据操作,通常在memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络I\O的次数和数据体积。在redis中,这些复杂的操作通常和一般的get/set一样高效,所以,如果需要缓存能够支持更复杂的结构和操作,那么redis是不错的选择。
  • redis优势:
    • memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型;
    • Redis的访问速度比memcached快很多;
    • Redis可以持久化其数据volatile
    • Redis支持数据的备份,即:master-slave模式的数据备份;
    • 使用底层模型不同,她们之间底层实现方式以及与客户端之间通信的应用协议不一样。Redis直接自己构建了VM机制,因为一般的系统调用系统函数的话会浪费一定的时间去移动和请求。
    • value大小,redis最大可达到1GB,而memcached只有1MB。
  • Redis持久化:
    • RDB:可丢失数据,但是效率高,redis默认持久化方式
    • AOF:不丢失数据。
  • 为什么Redis设计成单线程模型:
    • 因为redis是基于内存的操作,CPU不是redis的瓶颈,redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章的采用单线程的方案了。
        • 编程简单:相较于多线程的实现方式,单线程实现较为简单。
        • 并发帮助:采用并发操作实现类似多线程的效果。
        • 计算量小。Redis主要用于存储数据,CPU不是瓶颈,网络通常是瓶颈。如果应用程序设计正确。能够避免I/O阻塞,下称僵尸最后需要担心的问题。
        • 部署简单,由于redis是单线程,故能部署在低端单核CPU机器上,redis利用队列技术将并发访问变成为串行访问,消除传统数据库穿行控制的开销。
          1. 单线程的好处:
            1. 代码更清晰,处理逻辑简单;
            2. 不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
            3. 因为是单线程,所以同一时刻只能有一个操作,所以耗时的命令会导致并发下降,不只是读并发,写并发也会下降,而单一线程也只能用到一个CPU核心,所以可以在同一个多核服务器中,启动多个实例,组成master-slave或者master-master形式,耗时的读命令,完全可以在slave进行。
  • redis快的原因:
  • 完全基于内存
  • Redis 将数据储存在内存里面,读写数据的时候都不会受到硬盘 I/O 速度的限制,所以速度极快。
  • 连接数为10000时,QPS(每秒内查询次数可达90000)
  • 数据结构简单,对数据操作也简单
  • 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  • 使用多路 I/O 复用模型,非阻塞IO。(避免了使用锁)
    • 多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈。
  • 主要由以上几点造就了Redis 具有很高的吞吐量
  • Redis会有主从分离吗?
    • 有,“从”负责备份,“主”负责查询,当主机宕机又恢复后会从从机里恢复数据;
  • Redis 如何实现高可用?
    • Redis 高可用技术是为了解决 redis 宕机后影响整个服务的一种架构方式.主要采用主从结构来实现高可用.(主从挂载)
    • 高可用实现的方式有哨兵和集群 2 种方式.主要思想都是监听主节点的信息. 我们把这种监听方式称之为心跳机制.当在规定的时间内主节点没有响应,则判断主节点死亡.则会启动从节点代替主节点为用户提供服务.
  • Redis 分片机制是将多 reids 看做一个整体,每个 redis 只负责一个固定的区域.进行数据的更新和维护.这种方式的实现主要是基于 hash 一致性算法.根据 key 值计算出 hash 的位置,最终将数据保存.并且这个 key 值指向管理该区域的点

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值