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

本贴最后更新于 1618 天前,其中的信息可能已经事过景迁

一、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

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    286 引用 • 248 回帖 • 62 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...