redis你要知道的事

redis 的使用很广泛,若是你没有使用过 redis,都很差意思说本身是开发界的老司机。今天又到了知识普及时间。redis

聊到 redis,首先想到的是它的老表--Memcached。那么相比较它的老表,redis 有哪些闪光点呢?

一、持久化机制,能够按期将内存中的数据持久化到硬盘上。算法

二、binlog功能,能够将全部操做写入日志,当redis出现故障,可依照binlog进行数据恢复。数据库

三、支持virtual memory,能够限定内存使用大小,当数据超过阈值,则经过相似LRU的算法把内存中的最不经常使用数据保存到硬盘的页面文件中。缓存

四、支持的数据类型更多,使用的想象空间更大。服务器

五、支持实物。并发

固然,这些也能够看作 redis  的优势。除了这些,被你们熟知的就是--快。对滴,就是快,redis 是一个快男,可是有时候快并不必定坏事。dom

redis 优势

一、速度快。异步

二、支持丰富数据类型: String ,List,Set,Sorted Set,Hash 。分布式

三、丰富的特性。如订阅发布 Pub / Sub 功能、key 过时策略等。函数

四、持久化存储。

redis 缺点

一、过于依赖内存。

二、redis是单线程的,单台服务器没法充分利用多核服务器的CPU。

redis 是如何让本身变成快男的呢?

一、纯内存操做。

二、单线程,避免频繁上下文切换。

三、采用了非阻塞I/O多路复用机制。

四、使用底层模型不一样,Redis直接本身构建了VM 机制 ,由于通常的系统调用系统函数的话,会浪费必定的时间去移动和请求。(有钱真的能够随心所欲,自给自足。)

redis 使用久了,不可避免的会暴露出一些问题。小场面,不要慌,一切困难都是纸老虎,干就完了。

一、缓存穿透

- 恶意攻击,查询数据库中不存在的数据(未记录缓存)

- 方案:

一、利用互斥锁,缓存失效的时候,先去得到锁,获得锁了,再去请求数据库。没获得锁,则休眠一段时间重试。

二、用异步更新策略,不管key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存若是过时,异步起一个线程去读数据库,更新缓存。须要作缓存预热(项目启动前,先加载缓存)操做。

三、提供一个能迅速判断请求是否有效的拦截机制,好比,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。若是不合法,则直接返回。

二、缓存雪崩

- 缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而致使数据库链接异常。

- 方案:

一、缓存时间加随机数,设置不一样有效期,避免同时失效。

二、分布式部署,数据分散在不一样的redis和数据库。

三、永不过时(不建议)

三、缓存击穿

- 单一  key 很是热点,失效后直接请求数据库。

- 方案:

一、永不过时

二、互斥锁

四、redis 和数据库双写一致性问题

- 分布式常见问题。数据库和缓存双写,就必然会存在不一致的问题。

- 方案:首先,采起正确更新策略,先更新数据库,再删缓存。其次,由于可能存在删除缓存失败的问题,提供一个补偿措施便可,例如利用消息队列。

五、redis 并发竞争 key 问题。

- 同时有多个子系统去set一个key。

- 方案:

一、redis 事物机制,不适用 redis 集群(可能多个 key 不存储在一个 redis-server 上)。

二、(1)若是对这个key操做,不要求顺序

这种状况下,准备一个分布式锁,你们去抢锁,抢到锁就作set操做便可,比较简单。

(2)若是对这个key操做,要求顺序

假设有一个key1,系统A须要将key1设置为valueA,系统B须要将key1设置为valueB,系统C须要将key1设置为valueC.

指望按照key1的value值按照 valueA-->valueB-->valueC的顺序变化。这种时候咱们在数据写入数据库的时候,须要保存一个时间戳。假设时间戳以下

系统A key 1 {valueA  3:00}
系统B key 1 {valueB  3:05}
系统C key 1 {valueC  3:10}

那么,假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现本身的valueA的时间戳早于缓存中的时间戳,那就不作set操做了。以此类推。

其余方法,好比利用队列,将set方法变成串行访问也能够。总之,灵活变通。

redis 过时策略及内存淘汰机制

如下彻底复制来的,博主写的已经很是好了,不须要再修饰了,哈哈哈。

分析:

这个问题其实至关重要,到底redis有没用到家,这个问题就能够看出来。好比你redis只能存5G数据,但是你写了10G,那会删5G的数据。怎么删的,这个问题思考过么?还有,你的数据已经设置了过时时间,可是时间到了,内存占用率仍是比较高,有思考过缘由么?

回答:

redis采用的是按期删除+惰性删除策略。

为何不用定时删除策略?

定时删除,用一个定时器来负责监视key,过时则自动删除。虽然内存及时释放,可是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,所以没有采用这一策略.。

按期删除+惰性删除是如何工做的呢?

按期删除,redis默认每一个100ms检查,是否有过时的key,有过时key则删除。须要说明的是,redis不是每一个100ms将全部的key检查一次,而是随机抽取进行检查(若是每隔100ms,所有key进行检查,redis岂不是卡死)。所以,若是只采用按期删除策略,会致使不少key到时间没有删除。

因而,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key若是设置了过时时间那么是否过时了?若是过时了此时就会删除。

采用按期删除+惰性删除就没其余问题了么?

不是的,若是按期删除没删除key。而后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会愈来愈高。那么就应该采用内存淘汰机制

在redis.conf中有一行配置

# maxmemory-policy volatile-lru

该配置就是配内存淘汰策略的(什么,你没配过?好好检讨一下本身)

1)noeviction:当内存不足以容纳新写入数据时,新写入操做会报错。应该没人用吧。
2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用,目前项目在用这种。
3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。应该也没人用吧,你不删最少使用Key,去随机删。
4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,移除最近最少使用的key。这种状况通常是把redis既当缓存,又作持久化存储的时候才用。不推荐
5)volatile-random:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,随机移除某个key。依然不推荐
6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,有更早过时时间的key优先移除。不推荐

ps:若是没有设置 expire 的key, 不知足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。

 

老规矩,遇到好的文章要分享。

https://mp.weixin.qq.com/s/gEU8HtsQNPXY8bzkK-Qllg

https://zhuanlan.zhihu.com/p/106863808

https://zhuanlan.zhihu.com/p/134104400

相关文章
相关标签/搜索