redis事务作为一个命令执行的队列,将一系列的预处理的命令包装成为一个整体,当执行时按照添加顺序依次执行,中间不会被打断或干扰。因此redis采用multi、exec、discar进行对事务的处理。
开启事务:multi 关闭事务:exec 取消命令:discard
在传统的关系数据库中存在类似事务的ACID属性。然而在redis中也存在事务的原子性(Atomicity)、一致性(Consistency)、隔离性(Lsolation)以及在持久化时存在持久性(Durability)。具体ACID此处不展开叙述。学到redis的人应该之前都知道ACID
redis与关系型数据库还是有很大的区别,例如在mysql的InnoDB存储引擎中具有支持事务的处理,以及在SQL中他们都支持事务的回滚机制,但是在mysql中并不存在这种机制。
PS:有的人会认为discard是事务的回滚,这种认为是错误的,他只是在事务开启后输入discard指令,然后取消预处理队列中的所有命令也就是取消事务。
总的来说就是,我们开启客户端后输入mutil指令,开启事务,事务开启后,就可进行get set操作。直到我们输入exec,开始进行事务处理,或者是遇到discard取消事务。
也许这时候你会想到,万一我写的时候命令写错了怎么办,嗯,没事他会取消所有的指令操作,也就是取消整个事务。然后可能你还会想到,万一我指令没写错,数据写错了怎么办呢,emmmmm,那就祝你好运吧,你懂的。
当我们在进行某些操作时需要对其加锁处理,redis也提供相应的操作。
watch监视锁:对某个key进行监视,key一旦发生改变则不再执行
这里也许你会想到说,这只是监视锁,我想要的是当我做操作的时候其他人不可以做,只有等我结束了其他人才可以做,别急我们来看看下面的分布式锁。
当一个线程真正执行的过程中,不允许其他线程的操作,也就是在做操作之前判断是否有锁,如果有锁,说明有线程在执行,进入等待状态,直到锁被释放后得到锁,然后加锁–执行–释放。
有一天你去广场上看大妈们跳广场舞。突然,这时候你肚子疼。但是这个广场只有一个公共卫生间每次只能共一个人使用。然后你就飞快的跑着过去,突然你发现门从里面被反锁了。然后你没办法,只能在外面等待里面的人出来,这时候门开了,你飞快跑进去。然后关门、上锁,开始拉粑粑,直达拉好,然后你开锁,然后打开门出来,下一个人进去。
在这个例子中,你卫生间就相当于公共资源,每当一个人进去之后就会关上门(加锁)当一个人使用的时候另一个人只能进入等待状态,直到锁打开(锁被释放)才能够获得其资源。
**PS:**在我们处理分布式锁的时候通常事微秒或毫秒级别的,因此加锁时间不宜过大,具体时间需要业务测试后确认。
设定时间推荐: 最大耗时120%+平均网络延迟110 or 最大耗时<<网络平均时延,则取网络延时,反之相反
redis采用的是内存数据库。除了持久化以外的文件,所有的数据均在内存中进行运行,但有些数据并不是有效的,因此出现了删除策略。
删除策略包括:定时删除、惰性删除、定期删除
在分别讲述删除策略时,我们先来看一下下面的这个图:
我们在进行信息存储的时候Redis不仅仅会进行一个信息的存储,同时还会分配出expires空间,通过地址关联存储key的过期时间。
创建一个定时器,当达到时间,定时器工作,删除其指令与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执行时间到期,停止执行,下次继续相同位置执行
特点:
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进阶:集群–小白的进阶教程(二)(理论+图解+实践:一文了解集群)
redis更多早期随笔:
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://blog.csdn.net/qq_40432886/article/details/106909151
❤️ 如有错误欢迎指出❤️
❤️ 点击访问更多个人博客 www.wslhome.top❤️
❤️感谢Thanoslee1993:提指出存在的问题。有什么问题欢迎指出