Redis进阶

Redis的过期策略和内存淘汰机制

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

为什么不用定时删除?

定时删除,也可以说是实时删除,用一个定时器监控key,过期则删除。虽然即使释放了内存空间,但十分消耗CPU资源。

定期删除,redis默认每100ms检查是否有key过期。不是每隔100ms便将所有key检查一遍,而是随机抽取进行检查。因此,如果只采用定期删除策略,会导致很多key到时间后没有被删除。

惰性删除,在获取某个key时,redis会检查这个key是否过期,如果过期了此时就会被删除。

定期删除+惰性删除能够做的一劳永逸吗?

如果有些key过期后,在定期删除时不会被随机检查到,而且也几乎不会被访问,这些key就会一直存在。

redis的解决方案:内存淘汰机制

在redis.conf中有一行配置:

maxmemory-policy volatile-lru

volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

Redis如何处理大量请求

redis是一个单线程程序,即同一时刻只能处理一个客户端请求。(单线程避免了频繁的线程上下文切换

redis是通过IO多路复用的方式来处理多个客户端请求的,保证系统的高吞吐量。由于redis是基于内存运行,所以其处理单个客户端请求会很快,数据传输过程的阻塞时间完全可以忽略。

也就是说,redis避免了频繁的线程的上下文切换后,CPU不会是其瓶颈,其瓶颈在于内存和网络带宽

为什么要用IO多路复用这种技术呢?

Redis是跑在单线程的,所有的IO操作都是按照顺序线性执行,但由于一些读写操作等待用户输入或输出是阻塞的,如果其他IO操作都在等待阻塞操作结束,那所有的IO操作都会被阻塞。

redis采用IO多路复用的方式,监听多个套接字,保证了某一操作被阻塞后,redis的单一线程仍能处理其他IO操作。

Redis分布式锁

分布式锁是控制分布式系统不同进程间访问共享资源的一种方式。多用于解决分布式系统下的多进程并发问题。

情景:线程A和线程B都共享某个变量X

如果是单机情况下(单JVM进程),线程之间共享内存,使用线程锁就可以解决并发问题。

如果是分布式情况下(多JVM进程),线程A和B可能不在同一JVM进程中,线程锁便无法起到作用,需要使用分布式锁来解决进程间的冲突问题

redis实现分布式锁的关键:

排他性:在同一时间只能有一个客户端获取到锁,其他客户端无法获取

避免死锁: 锁信息必须是会过期的,不能让一个线程一直占有锁而导致死锁。

除了锁自动过期之外,还可以解锁,加锁和解锁必须是同一线程。

Redis实现分布式锁,主要是依赖redis自身的原子操作:

SET user_key user_value NX PX 100

NX:只在在键不存在时,才对键进行设置操作,SET key value NX 效果等同于 SETNX key value。
PX 100:设置键的过期时间为100毫秒。

当某个进程设置成功之后,就可以去执行业务逻辑了,等业务逻辑执行完毕之后,再去进行解锁。
解锁很简单,只需要删除这个key就可以了,不过删除之前需要判断,这个key对应的value是当初自己设置的那个。

如果一个锁过期但线程业务还没执行完,怎么办?

可以创建一个守护线程,一直为锁续期。如果主线程没执行完,守护线程也不会死掉,直到主线程执行完毕。

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页