文章目录

  • 概述
  • redis是什么?
  • redis的优缺点
  • redis为什么这么快
  • Redis和Memcached的区别
  • 数据类型
  • Redis支持哪些数据类型?
  • 缓存问题
  • 缓存雪崩
  • 缓存穿透
  • 缓存击穿
  • 过期键的删除策略
  • 内存淘汰策略


学习参考:

概述

redis是什么?

redis是C语言开发的一个开源的高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件等。

redis的优缺点

优点

  1. 性能优秀,数据在内存中,读写速度快;
  2. 丰富的数据类型,除了支持string类型的value外还支持hash、set、zset、list等数据结构;
  3. 支持数据持久化,支持AOF和RDB两种持久化方式;
    可以将内存中的数据保存磁盘中,重启时加载。
  4. 支持主从复制哨兵高可用集群等模式;
  5. 可以用作分布式锁、可以用作消息中间件使用;

缺点

  1. 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上;
  2. Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复;
  3. 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性;
  4. Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费;

redis为什么这么快

  1. redis完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);
  2. 数据结构简单,对数据的操作也简单;
  3. 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  4. 使用多路 I/O 复用模型,非阻塞 IO;

Redis和Memcached的区别

  1. 存储方式上:Memcached把全部数据保存在内存中,数据不能超过内存大小;一旦服务器挂掉,数据不可恢复。Redis有部分数据保存在磁盘上,这样能保持数据的持久性。
  2. 数据支持类型上:Memcached对数据类型的支持简单,只支持简单的key-value,而Redis支持5种数据类型(string、list、hash、set、zset)。
  3. Value的大小:Redis可以达到1GB,而Memcached只有1MB。
  4. 持久化的支持:Memcached不支持持久化;而Redis支持持久化,有2种方式(RDB、AOF)。

数据类型

Redis支持哪些数据类型?

Redis的广播模式 redis语音_数据

缓存问题

缓存雪崩

缓存雪崩是指缓存同一时间大面积失效,导致请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方法

  1. 缓存时间的过期时间设置随机,避免同一时间大量缓存失效的现象发生;
  2. 设置热点数据永不过期,
  3. 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。

缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,用户(黑客)不断发起请求。
举个例子:数据库id从1开始自增,如果发起id=-1或者id特别大不存在的数据,这样不断的攻击导致数据库压力很大,严重的话会导致数据库崩掉。

解决方法

  1. 接口层做校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
  3. 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力

缓存击穿

缓存击穿跟缓存雪崩有点像,但是又有点不一样。缓存雪崩是因为大面积的缓存缓存失效,打崩了数据库;而缓存击穿是因为一个非常热点的缓存失效,打崩了数据库。

缓存击穿是指一个key非常热点,在不停的扛着大量的请求,大并发集中对这个点进行访问,当这个key在失效的瞬间,持续的大并发直接落在数据库上,就在这个key的点上击穿了缓存。

解决方法

  1. 设置热点数据永不过期
  2. 加互斥锁
    互斥锁代码 示例:

过期键的删除策略

我们可以设置redis中key的过期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。

Redis的过期键删除策略有以下3种:

  1. 定时删除:在设置键的过期时间的同时,创建一个定时任务,当键达到过期时间时,立即执行对键的删除操作。
    优点:对内存友好,定时删除策略可以保证过期键会尽可能快地被删除,并释放过期键所占用的内存。
    缺点:对cpu时间不友好,在过期键比较多时,删除任务会占用很大一部分cpu时间,在内存不紧张但cpu时间紧张的情况下,将cpu时间用在删除和当前任务无关的过期键上,影响服务器的响应时间和吞吐量
  2. 惰性删除:任键过期不管,但在每次从键空间获取键时,都检查取得的键是否过期,如果过期的话,就删除该键,如果没有过期,就返回该键。
    优点:对cpu时间友好,在每次从键空间获取键时进行过期键检查并是否删除,删除目标也仅限当前处理的键,这个策略不会在其他无关的删除任务上花费任何cpu时间。
    缺点:对内存不友好,过期键过期也可能不会被删除,导致所占的内存也不会释放。甚至可能会出现内存泄露的现象,当存在很多过期键,而这些过期键又没有被访问到,这会可能导致它们会一直保存在内存中,造成内存泄露。
    3.定期删除:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
    (expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)

内存淘汰策略

Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。

Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据。

Redis的过期键删除策略有:

Redis的广播模式 redis语音_redis_02

全局的键空间选择性移除

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

allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。

allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。

设置过期时间的键空间选择性移除
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。