文章目录
redis_redis_3">一、什么是redis? redis的作用?
Redis 英文全称是Remote Dictionary Server(远程字典服务),是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,可以用来做数据库、缓存、消息中间件等场景,是一种NoSQL(not-only sql,非关系型数据库)的数据库。
它的读写速度非常快,每秒可以处理超过10万次读写操作。经常用来做分布式锁,支持事务、持久化、LUA 脚本、LRU 驱动事件、多种集群方案。
redis_6">二、redis的特点
- 优秀的性能,数据是存储在内存中,读写速度非常快,可支持并发10W QPS
- 单线程但进程,是线程安全的,采用IO 多路复用制
- 可作为分布式锁
- 支持五种数据类型
- 支持数据持久化到磁盘
- 可以作为消息中间件使用,支持消息发布及订阅
redis_13">三、redis的基本数据结构类型
它还有三种特殊的数据结构类型
- Geospatial
- Hyperloglog
- Bitmap
redis__19">四、redis 的三种特殊数据类型
Geo:Redis3.2推出的,地理位置定位,用于存储地理位置信息,并对存储的信息进行操作。
HyperLogLog:用来做基数统计算法的数据结构,如统计网站的UV。
Bitmaps :用一个比特位来映射某个元素的状态,在Redis中,它的底层是基于字符串类型实现的,可以把bitmaps成作一个以比特位为单位的数组
redis__23">五、redis 作为缓存
数据缓存是Redis最重要的一个场景,为缓存而生,在springboot中,一般有两种使用方式:
- 直接通过RedisTemplate使用
- 通过Spring Cache集成Redis(也就是注解的方式)
redis__27">六、redis 作为缓存存在的问题
6.1 数据一致性
在分布式环境下,缓存和数据库很容易出现数据一致性问题,如果项目对缓存的要求是强一致性,那就不要使用缓存。
我们只能在项目中使用策略降低缓存与数据库一致性的概率,是无法保障两者的强一致性,一般策略包括缓存更新机制,更新数据库后及时更新缓存、缓存失败时增加重试机制等方式。
6.2 缓存雪崩
假设A系统每秒需要处理5000个请求,但数据库每秒只能处理4000个请求,某一天,缓存机器出现了宕机,挂了,这时候所有的请求一下子全部落在数据库上,数据库肯定扛不住,报警挂掉了,这时候如果没有采取缓存设施,数据库又急着用,重新重启数据库,刚重启完成(有可能没启动完),请求又来,数据库立马挂掉。这就是雪崩事件,是Redis缓存中最致命问题之一(有一个是穿透)。
我们可以在事故前中后三个方面来思考解决方案
- 事故前:redis高可用方案,主从+哨兵,集群方案,避免全盘崩溃
- 事故中:较少数据库的压力,本地Ehcache缓存+限流及降级,避免超过数据库承受压力
- 事故后:做redis持久化,一旦Redis重启,可从磁盘中快速恢复数据
改造后的数据流程,假设用户A发送一个请求,系统先请求本地Ehcache是否有数据,如果没有再去Redis请求数据,如果没有再去数据库请求数据,获取到数据后同步到Ehcache和redis
限流的作用:可以设置每秒请求数次,有多少通过请求,剩余的未通过的可以走降级处理,返回一些默认的值,或者友情提示等默认操作。具体流程可以看看下图:
数据库安全:在限流组件可用的情况下,数据库不会挂掉,限流根据确保了每秒多少请求能通过。
部分请求可以被处理:数据库没挂,就意味着至少2/5的请求可以被处理掉
高峰时期部分请求无法处理到,需要用户多次点击,因为只有2/5的请求被处理,剩下的请求,用户刷不出来界面,需要多点击几次
redis设置的缓存失效时间不是设置成同一个时间,可根据功能、业务、请求接口灵活设置缓存时间:setRedis(key, value, time+Math.random()*10000)。
6.3 缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,用户(黑客)不断发起请求,导致请求直接查询数据库,这种恶意行为攻击场景的会直接导致数据库挂掉。
可以采取以下方案:
- 在请求接口层可以做一些校验,比如用户签权、参数校验,不合法的请求直接return。
- 还可以针对有效id做认证或直接拦截,不符合的id直接过滤或采用统一key保存到redis,下次不合法的id请求时,直接到缓存中获取数据。
- 采用redis的高级接口Bloom Filter,利用高效的数据结构和算法快速判断出你这个 Key 是否在数据库中存在,不存在你return 就好了,存在你就去查 DB 刷新 KV 再 return。
6.4 缓存击穿
穿透是针对大面积数据请求,那么击穿是针对一点(一个key)来来导致redis异常,但某个key是非常热点,请求非常频繁,处于集中式访问现象,当这个key失效(过期)时,大量的请求就会击穿了缓存,直接请求数据库,就像在屏障中凿开了一个洞。
不同场景下缓存击穿解决方案
数据基本不变:热点数据value基本不更新时,可以设置成永不过期
数据更新不频繁:缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
数据更新频繁:采用定时线程,在缓存过期前主动重新构建缓存或延长过期时间,保证所有的请求能一直访问缓存
redis_59">七、redis为什么那么快?
redis 是单进程单线程的模型,完全基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈是内存及网络带宽,有以下特点:
- 使用类似于HashMap的原理,HashMap的查询及操作的时间复杂度是O(1),且绝大多数请求是纯碎的内存操作,数据存在内存中。
- 数据结构简单,对数据操作也简单,基于KV。
- 不错死锁现象采用单线程操作,避免了不必要的上下文切换及竞争条件,不存在CPU切换现象,也就不存在考虑各种锁的问题。
- 使用非阻塞IO,多路复用IO模型。
redis_66">八、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当前存放30万个key,并且都设置了过期时间,如果你每隔100ms就去检查这全部的key,CPU负载会特别高,最后可能会挂掉。
- 因此,redis采取的是定期过期,每隔100ms就随机抽取一定数量的key来检查和删除的。
- 但是呢,最后可能会有很多已经过期的key没被删除。这时候,redis采用惰性删除。在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间并且已经过期了,此时就会删除。
但是呀,如果定期删除漏掉了很多过期的key,然后也没走惰性删除。就会有很多过期key积在内存内存,直接会导致内存爆的。或者有些时候,业务量大起来了,redis的key被大量使用,内存直接不够了,运维小哥哥也忘记加大内存了。难道redis直接这样挂掉?不会的!Redis用8种内存淘汰策略保护自己~
redis__83">九、redis 内存淘汰策略
volatile-lru:当内存不足以容纳新写入数据时,从设置了过期时间的key中使用LRU(最近最少使用)算法进行淘汰;
allkeys-lru:当内存不足以容纳新写入数据时,从所有key中使用LRU(最近最少使用)算法进行淘汰。
volatile-lfu:4.0版本新增,当内存不足以容纳新写入数据时,在过期的key中,使用LFU算法进行删除key。
allkeys-lfu:4.0版本新增,当内存不足以容纳新写入数据时,从所有key中使用LFU算法进行淘汰;
volatile-random:当内存不足以容纳新写入数据时,从设置了过期时间的key中,随机淘汰数据;。
allkeys-random:当内存不足以容纳新写入数据时,从所有key中随机淘汰数据。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的key中,根据过期时间进行淘汰,越早过期的优先被淘汰;
noeviction:默认策略,当内存不足以容纳新写入数据时,新写入操作会报错。
redis_92">十、redis持久化
Redis 持久化策略有两种:
- RDB:快照形式是直接把内存中的数据保存到一个 dump 的文件中,定时保存,保存策略。
- AOF:把所有的对 Redis 的服务器进行修改的命令都存到一个文件里,命令的集合。Redis 默认是快照 RDB 的持久化方式。
如果非常关心你的数据,但仍然可以承受数分钟内的数据丢失,那么可以额只使用 RDB 持久。
AOF 将 Redis 执行的每一条命令追加到磁盘中,处理巨大的写入会降低Redis的性能,不知道你是否可以接受。
数据库备份和灾难恢复:定时生成 RDB 快照非常便于进行数据库备份,并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度快。
当然了,Redis 支持同时开启 RDB 和 AOF,系统重启后,Redis 会优先使用 AOF 来恢复数据,这样丢失的数据会最少。
本文参考:一文读懂Redis
感谢您的观看,希望对您有帮助,发财的小手点点赞,点点关注~