Redis进阶(事务、锁、删除策略、逐出算法)

2020-06-17

一、Redis事务管理

  • 简介:

redis事务作为一个命令执行的队列,将一系列的预处理的命令包装成为一个整体,当执行时按照添加顺序依次执行,中间不会被打断或干扰。因此redis采用multi、exec、discar进行对事务的处理。

开启事务:multi 关闭事务:exec 取消命令:discard

  • redis事务的特性:

在传统的关系数据库中存在事务的ACID属性。然而在redis中也存在事务的原子性(Atomicity)、一致性(Consistency)、隔离性(Lsolation)以及在持久化时存在持久性(Durability)。具体ACID此处不展开叙述。学到redis的人应该之前都知道ACID

  • 注意事项:

redis与关系型数据库还是有很大的区别,例如在mysql的LnnoDB存储引擎中具有支持事务的处理,以及在SQL中他们都支持事务的回滚机制,但是在mysql中并不存在这种机制。

PS:有的人会认为discard是事务的回滚,这种认为是错误的,他只是在事务开启后输入discard指令,然后取消预处理队列中的所有命令也就是取消事务。

  • 执行过程:

总的来说就是,我们开启客户端后输入mutil指令,开启事务,事务开启后,就可进行get set操作。直到我们输入exec,开始进行事务处理,或者是遇到discard取消事务。

image.png

  • 测试案例:

image.png

  • 闲谈:

也许这时候你会想到,万一我写的时候命令写错了怎么办,嗯,没事他会取消所有的指令操作,也就是取消整个事务。然后可能你还会想到,万一我指令没写错,数据写错了怎么办呢,emmmmm,那就祝你好运吧,你懂的。

二、Reids锁

当我们在进行某些操作时需要对其加锁处理,redis也提供相应的操作。

watch监视锁:对某个key进行监视,key一旦发生改变则不再执行

  • 未加监视锁:

image.png

  • 启监视锁:

image.png

  • 闲谈:

这里也许你会想到说,这只是监视锁,我想要的是当我做操作的时候其他人不可以做,只有等我结束了其他人才可以做,别急我们来看看下面的分布式锁。

三、分布式锁

  • 说明:

当一个线程真正执行的过程中,不允许其他线程的操作,也就是在做操作之前判断是否有锁,如果有锁,说明有线程在执行,进入等待状态,直到锁被释放后得到锁,然后加锁--执行--释放。

  • 举个例子:

有一天你去广场上看大妈们跳广场舞。突然,这时候你肚子疼。但是这个广场只有一个公共卫生间每次只能共一个人使用。然后你就飞快的跑着过去,突然你发现门从里面被反锁了。然后你没办法,只能在外面等待里面的人出来,这时候门开了,你飞快跑进去。然后关门、上锁,开始拉粑粑,直达拉好,然后你开锁,然后打开门出来,下一个人进去。

在这个例子中,你卫生间就相当于公共资源,每当一个人进去之后就会关上门(加锁)当一个人使用的时候另一个人只能进入等待状态,直到锁打开(锁被释放)才能够获得其资源。

  • 案例:QQ截图20200617205745.png

**PS:**在我们处理分布式锁的时候通常事微秒或毫秒级别的,因此加锁时间不宜过大,具体时间需要业务测试后确认。

设定时间推荐: 最大耗时120%+平均网络延迟110 or 最大耗时<<网络平均时延,则取网络延时,反之相反

四、删除策略

redis采用的是内存数据库。除了持久化以外的文件,所有的数据均在内存中进行运行,但有些数据并不是有效的,因此出现了删除策略。

删除策略包括:定时删除、惰性删除、定期删除

  • 引入:

在分别讲述删除策略时,我们先来看一下下面的这个图:

我们在进行信息存储的时候Redis不仅仅会进行一个信息的存储,同时还会分配出expires空间,通过地址关联存储key的过期时间。

image.png

  • 定时删除:

创建一个定时器,当达到时间,定时器工作,删除其指令与expires空间中内容。

换句话说就是我们set的时候在设定过期时间的同时也就创建了一个定时器,当时间一到,定时器响应,然后删除其key相关的所有东西。

优点:

节约内存、到时就删除、快速释放内存

缺点:

CPU压力大,无论CPU压力有多大都会占用CPU,同时影响redis服务器的相应时间与吞吐量

PS:用CPU性能换取存储空间(拿时间换空间)

  • 惰性删除

简单描述就是当数据过期后不做任何处理,当下次访问时候再将数据删除

也就是我们在设定key的过期时间,key过期了,虽然我们不能够进行操作,但是他仍然存在于内存之中,而每次我们对key进行访问时会调用expirelfNeeded()进行是否过期判断,如果过期则将其删除,没有过期则继续操作。

优点:

节约CPU性能,发现必须删除时候才进行删除

缺点:

内存压力大,出现长期占用内存的情况

PS:用存储空间换处理器性能(拿空间换时间)

  • 定期删除

定时删除需要花费更多的时间,惰性删除需要花费更多的空间,而定期删除进行了二者的折中,采用周期性轮询Redis数据的时效性,采用随机读取的策略,采用过期数据占比的方式控制删除的频度。

具体实现:

如果觉得下面的废话太多,直接看图。

当redis服务器进行初始化时,会对配置文件进行读取,读取其中的server.hz的值(默认大小为10)进行操作。然后进行每秒钟执行server.hz次serverCron()操作。而每次的serverCron()操作都会对所有的数据库进行databaseseCron()轮询。在轮询过程中执行axtiveExpireCyle()操作。而对于每一个expires[*]进行逐一的检测,每次执行250ms/server.hz个。在检测过程中会采用随机挑选W个值进行检测,如果检测到key超时就将其删除。而在一次轮询中删除的key数量大于25xW时,则再次循环这个过程,如果小于等于25xW则检测下一个expire。

*W取值=ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 属性值
参数Current_db记录每次activeExpireCycle进入到那个expires[*]执行
如果activeExpirecycle执行时间到期,停止执行,下次继续相同位置执行

image.png

image.png

特点:

  1. cpu的性能设有峰值,检测频度可以自己设定
  2. 内存压力不大,长期常用内存的过期数据会被持续性清除

PS
随机性抽查,重点抽查存储空间

五、逐出算法

定义:

redis使用内存存储数据,在执行每一个命令之前,都会调取freeMemorylfNeeded()进行检测内存是否充足,如果内存不满足新书加入数据的最低要求,redis要临时删除一些数据为当前指令清出存储空间,清除数据的策略称之为逐出算法。

注意:

逐出过程不是100%能够清理出足够的内存空间,当不成功时候会反复执行,当对所有的数据都尝试完毕后,还没有达到内存的清理的要求就会抛出错误信息:

(error)OOM command not allowed when used memomry>'maxmemory'

配置:

maxmemory 最大的可用内存(占用物理内存的比例,默认为0,表示不限制,生产环境中根据需求设定,通常设置在50%以上)
maxmemory-samples:每次选取删除数据的个数,(选取数据时并不会全库扫描,导致严重的性能消耗,降低读写性能,因此采用随机获取数据的方式作为待检测删除数据策略)

策略配置:eg:maxmemory-policy volatile-lfu

检测易失数据(可能会过期的数据server.db[i].expire)
	volatile-lru:挑选最近没有使用过的数据淘汰
	volatile-lfu:挑选最近使用最少的数据淘汰
	volatile-ttl:挑选将要过期的数据淘汰
	volatile-random:任意选择数据淘汰
	检测全库数据:(所有数据集server.db[i].dict)
	allkeys-lru:挑选长时间未使用的数据
	allkeys-lfu:挑选最近使用次数最少的数据
	allkeys-random:任意选择淘汰
	no-enviction:禁止驱逐数据(4.0中默认策略。会引发OOM)

调优:

InFO:查看hit命中与miss的次数然后进行调优

❤️给❤️梦❤️想❤️一❤️点❤️点❤️时❤️间❤️让❤️它❤️一❤️步❤️步❤️成❤️长❤️

💪加油!!! 💪


redis更多早期随笔:

redis持久化(RDB与AOF)的方式比较:https://www.wslhome.top/articles/2020/06/16/1592312734423.html

redis搭建、redis命令、基础知识:
https://www.wslhome.top/articles/2020/06/12/1591944857524.html

redis 五种基本数据格式原理与应用:
https://www.wslhome.top/articles/2020/06/16/1592312用CPU性能换取存储空间(拿时间换空间)
内存压力大,出现长期占用内存的


标题:Redis进阶(事务、锁、删除策略、逐出算法)
作者:sirwsl
地址:https://www.wslhome.top/articles/2020/06/17/1592377207134.html