什么是redis
一个用C语言开发的单进程单线程的NOSQL数据库,由于数据保存在内存中,所以redis特别快,理论速度可以达到11万次/秒的读取。8万/次的写入。redis支持多种数据类型,提供了丰富的使用场景,支持事务监听等功能。’redis也支持数据的持久化操作。
redis的数据类型
string
传送门 :Redis 之 string类型
list
传送门: Redis 之 list数据类型
hash
传送门: Redis 之 hash类型
set
暂无传送门~
zset
暂无传送门~
redis用途
缓存
这是我们最常用的。用于当做web应用程序的第三方缓存。
面对一些查询量相当大的业务,我们为了减轻接口或者DB的压力,就会将查询出来的数据保存到redis中。
当相同的查询请求再进来时直接读取redis中的数据。加快响应速度。
分布式系统中session共享
分布式架构中,我们可以将session进行加密成token,然后放入requestHander中,每次请求带着token,微服务接收到请求之后,拿着token解密之后的sessionid去redis中查询,找出对应的session,这样就实现了分布式系统中的session共享。
计数器
计数器的应用就比较多了。举个简单例子就是一个手机号多次发送短信,我们怀疑他恶意刷我们系统,我们可以将每次请求记录加1存入redis并设置一个超时时间,当达到我们指定的次数后,限定其指定时间内不允许再次发送。
抽奖
使用set集合,存入不可重复的抽奖名称,然后使用随机弹出几个key。
队列
我们可以用list实现队列。比如朋友圈推送?A有B,C两个朋友,分别发了两个朋友圈B1,C1。我们将他们放入A的朋友圈更新队列中。每次让他从右侧弹出指定10条或者100条朋友圈。并不一定他们是这么实现的,我只是觉得这是一个可行的方案。
数据持久化
redis虽然是将数据存在内存之中,但是也提供持久化方式,有两种,一种是RDB模式,一种是AOF模式。
关于持久化内容,我单独写了一个博客,传送门:
redis缓存策略
redis提供了6中缓存策略:
noeviction
默认策略,当内存写满时,不在继续提供写服务;仅保留读服务;这会导致系统业务中断,不建议使用。
volatile-lru
淘汰设置了timeout的key中上次使用时间距淘汰时的时间最长的key,没设置timeout的key不会被清除。保证持久化的数据不丢失。
key中维护了一个24位时间,LRU算法是根据当前时间与key最后被使用时间做比较,决定是否淘汰。
volatile-lfu
从redis4.0开始,新增了LFU策略。淘汰设置了timeout的key中使用最少的key。相比LRU更精确。
LFU算法将24位时间拆分为16位时间+8位计数器。是根据当前时间与key的最后使用时间,与使用数量,最比较。
比如keyA在过去一段时间内经常被使用,清理前没有被使用,而keyB一直没有被使用过,在清理前却被使用了一次。那么根据LRU算法,会淘汰掉使用率更高的A而新的LFU算法则会淘汰B。
volatile-ttl
淘汰设置了timeout的key中剩余时间最少的key。其余和volatile-lru一致。
volatile-random
随机淘汰一批设置了timeout的key。
allkeys-lru
除了淘汰的是全部key以外,同volatile-lru。这个策略可以在座位缓存服务器时使用。保证key在最后保留的都是热点key。
allkeys-lfu
除了淘汰的是全部key以外,同volatile-lfu。这个策略可以在座位缓存服务器时使用。保证key在最后保留的都是热点key。
allkeys-random
随机淘汰一批key,包括持久化的key。不建议使用。
redis的过期策略
定期删除
redis将设置过timeout的key放到一个字典中,每100ms会扫描一遍这个字典,扫描方式是随机抽取20个key进行扫描。清除过期的key。
惰性删除
当我们查询某个key时,他会再去检查一下是否有超时时间,是否到达超时时间。如果已经超时则将其清除。
过期策略也是两个策略共同使用来保证key的过期。
缓存雪崩
雪崩,大面积问题。即redis服务器挂了或者一时间大面积key过期大面积key的导致流量进入db。
比如:我们的web应用高峰时db可承受并发量是1000/秒;我们使用了redis作为缓存服务器后,web应用并发得到扩展,有5000/秒,这时候发生缓存雪崩,压力瞬间都到db中,瞬间就将db压垮了。如此之高的请求可能当我们再重启db时又瞬间被压垮。导致整个web服务不可用。这就是缓存雪崩。
如果是redis崩了,我们可以通过集群部署redis+主从冷备+哨兵;如果是大量key过期失效,我们可以使用随机过期时间处理。
缓存击穿
击穿,像子弹一样打穿一个点。即redis的某个热点key过期导致的大量流量从一个点进入db。
和缓存雪崩不一样,雪崩只大量缓存集中过期导致的;而击穿指某个热点key,突然过期导致db压力暴增。
解决办法:1、热点key的定期刷新。2、热点key的db查询功能加锁。防止热点key的大量重建进入。并且将热点key再次加入缓存。即使热点key过期也仅需一次db请求即可。后续又可以从redis缓存中获取到。
缓存穿透
穿透,像没有一样穿过去。即redis中没命中,去查db也没命中。所以也不会有结果被缓存到redis中,这类请求一直打进来,会导致redis没有作用。透明一样。
我们做缓存一般是将查询到的数据去存入redis 如果db中查不到的那么redis中也没有的。就会出现问题,当有人恶意发起访问,一直高并发去请求这类数据,就会绕过缓存直接攻击到数据库’。所以,我们可以使db中查询不到的信息也放入redis,设为空。这样就避免了对db的直接攻击。或者使用布隆过滤器。布隆过滤器即将一个key通过多个hash算法进行运算,放入一个大的bitmap中。一个一定不存在的数据会被布隆过滤器拦截。
缓存预热
预热,预先放入缓存。提高缓存命中率。
有些数据是我们经常要用的,这些数据也不会经常改变,那么我们可以使系统在初始化时就加载到缓存中,直接通过缓存来使用。这就叫缓存预热。提前讲缓存准备好,使其根本不需要去查询db。
缓存降级
在超大并发下的,对业务功能的取舍。