Redis-事务、布隆过滤器及过期策略【随笔二】

本文详细介绍了Redis的事务机制,包括管道、消息订阅、乐观锁(WATCH命令)以及ACID性质。此外,还探讨了布隆过滤器的概念、实现原理和应用,以及Redis的过期键删除策略和内存回收策略。通过对这些特性的理解,可以更好地优化Redis的性能和数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

管道(pipeline)

向服务器发送多个命令,最后一步统一读取回复;这就是管道(pipelining),是一种几十年来广泛使用的技术。例如许多 POP3 协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。

管道不仅仅是一种减少与往返时间相关的延迟成本的方法,它实际上大大提高了您在给定 Redis 服务器中每秒可以执行的操作数量。这是因为在不使用管道的情况下,从访问数据结构和产生回复的角度来看,为每个命令提供服务非常便宜,但从执行套接字 I/O 的角度来看却非常昂贵。这涉及调用 read()write() 系统调用,这意味着从用户空间到内核空间。上下文切换是一个巨大的速度损失。

使用管道时,通常使用单个 read() 系统调用读取许多命令,并使用单个系统调用传递多个回复 write()。正因为如此,每秒执行的总查询数最初随着管道的延长几乎呈线性增长,最终达到不使用管道获得的基线的 10 倍

管道:将多个命令一次性发送过去,降低通信成本

redis-cli
yum install nc
nc localhost 6379
keys*
set k1 hello

echo -e "set k2 99\n incr k2\n get k2" | nc localhost 6379

消息订阅(Pub/Sub)

订阅,取消订阅和发布实现了发布/订阅消息范式(引自 wikipedia),发送者(发布者)不是计划发送消息给特定的接收者(订阅者)。而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅。订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不需要知道什么样的发布者发布的。这种发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑。

模式匹配订阅

Redis 的 Pub/Sub 实现支持模式匹配。客户端可以订阅全风格的模式以便接收所有来自能匹配到给定模式的频道的消息。

PSUBSCRIBE news.*

将接收所有发到 news.art.figurative, news.music.jazz 等等的消息,所有模式都是有效的,所以支持多通配符。

PUNSUBSCRIBE news.*

将取消订阅匹配该模式的客户端,这个调用不影响其他订阅。

当作模式匹配结果的消息会以不同的格式发送:

  • 消息类型是 pmessage: 这是另一客户端发出的 PUBLISH 命令的结果,匹配一个模式匹配订阅。第一个元素是原匹配的模式,第三个元素是原频道名称,最后一个元素是实际消息内容。

同样的,系统默认 SUBSCRIBEUNSUBSCRIBE, PSUBSCRIBEPUNSUBSCRIBE 命令在发送 psubscribe 和punsubscribe 类型的消息时使用像 subscribe 和 unsubscribe 一样的消息格式。

同时匹配模式和频道订阅的消息

客户端可能多次接收一个消息,如果它订阅的多个模式匹配了同一个发布的消息,或者它订阅的模式和频道同时匹配到一个消息。就像下面的例子:

SUBSCRIBE foo
PSUBSCRIBE f*

上面的例子中,如果一个消息被发送到 foo, 客户端会接收到两条消息:一条 message 类型,一条 pmessage 类型。

PUBLISH ooxx hello

SUBSCRIBE ooxx
只能收到监听后发送的消息

Redis事务

基础概念
命令描述
MULIT标记一个事务块的开始
WATCH监视一个(或多个)key,如果在事务执行之前这个(或多个)key被其他命令所改动,那么事务将被打断
UNWATCH取消 WATCH 命令对所有 keys 的监视
EXEC执行所有事务块内的命令
DISCARD取消事务,放弃执行事务块内的所有命令

MULTIEXECDISCARDWATCH 是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

注意:这个原子操作,和关系型 DB 的原子性不太一样,它不能完全保证原子性

简单使用

Redis 事务使用分为三个阶段:

  • 开启事务(multi):MULTI 命令用于开启一个事务,它总是返回 OK
  • 命令入队(业务操作):MULTI 执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中。
  • 执行事务(exec)或取消事务(discard): 当 EXEC 命令被调用时, 所有队列中的命令才会被执行;另一方面, 通过调用 DISCARD, 客户端可以清空事务队列, 并放弃执行事务。

下面的指令演示了一个完整的事务过程,所有的指令在 exec 之前不执行,而是缓存在服务器的一个事务队列中,服务器一旦收到 exec 指令,才开执行整个事务队列,执行完毕后一次性返回所有指令的运行结果。

请添加图片描述

MULIT
SET K1 aaa
SET K2 bbb
EXEC

MULIT
DEL K1
EXEC

MULIT
GET K1
EXEC

WATCH K1   
MULIT     MULIT
GET K1    SET K1 333322
KEYS *    KEYS*
EXEC      EXEC

EXEC 命令负责触发并执行事务中的所有命令:

  • 如果客户端在使用 MULTI 开启了一个事务之后,却因为断线而没有成功执行 EXEC,那么事务中的所有命令都不会被执行。
  • 另一方面,如果客户端成功在开启事务之后执行 EXEC ,那么事务中的所有命令都会被执行。

EXEC 命令的回复是一个数组, 数组中的每个元素都是执行事务中的命令所产生的回复。 其中, 回复元素的先后顺序和命令发送的先后顺序一致。

当客户端处于事务状态时, 所有传入的命令都会返回一个内容为 QUEUED 的状态回复(status reply), 这些被入队的命令将在 EXEC 命令被调用时执行。

事务中的错误

使用事务时可能会遇上以下两种错误:

  • 事务在执行 EXEC 之前,入队的命令可能会出错。比如说,命令可能会产生语法错误(参数数量错误,参数名错误,等等),或者其他更严重的错误,比如内存不足(如果服务器使用 maxmemory 设置了最大内存限制的话)。
  • 命令可能在 EXEC 调用之后失败。举个例子,事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面,诸如此类。

对于发生在 EXEC 执行之前的错误,服务器会对命令入队失败的情况进行记录,并在客户端调用 EXEC 命令时,拒绝执行并自动放弃这个事务(Redis 2.6.5 之前的做法是检查命令入队所得的返回值:如果命令入队时返回 QUEUED ,那么入队成功;否则,就是入队失败)

至于那些在 EXEC 命令执行之后所产生的错误, 并没有对它们进行特别处理: 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。

EXEC 执行前


EXEC 执行后


最重要的是记住这样一条, 即使事务中有某条/某些命令执行失败了, 事务队列中的其他命令仍然会继续执行 —— Redis 不会停止执行事务中的命令,并且 Redis 不支持回滚【官方给的说法是失败的命令是由编程错误造成的,所以不需要提供回滚】

放弃事务

当执行 DISCARD 命令时, 事务会被放弃, 事务队列会被清空, 并且客户端会从事务状态中退出,如下:

> SET foo 1
OK
> MULTI
OK
> INCR foo
QUEUED
> DISCARD
OK
> GET foo
"1"
带 WATCH 的事务
基本概念

WATCH 命令用于在事务开始之前监视任意数量的键,如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消,EXEC 返回 nil-reply 来表示事务已经失败。

WATCH 命令可以被调用多次,对键的监视从 WATCH 执行之后开始生效, 直到调用 EXEC 为止;单个 WATCH 命令可以监视任意多个键, 就像这样:

redis> WATCH key1 key2 key3 
OK 

EXEC 被调用时, 不管事务是否成功执行, 对所有键的监视都会被取消。另外, 当客户端断开连接时, 该客户端对键的监视也会被取消。

WATCH 的使用

当多个客户端同时对同一个键进行这样的操作时, 就会产生竞争条件。举个例子, 如果客户端 A 和 B 都读取了键原来的值, 比如 10 , 那么两个客户端都会将键的值设为 11 , 但正确的结果应该是 12 才对。

有了 WATCH, 我们就可以轻松地解决这类问题了:

WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC

上面的代码, 如果在 WATCH 执行之后,EXEC 执行之前, 有其他客户端修改了 mykey 的值, 那么当前客户端的事务就会失败。 程序需要做的, 就是不断重试这个操作, 直到没有发生碰撞为止。

这种形式的锁被称作乐观锁, 它是一种非常强大的锁机制。 并且因为大多数情况下, 不同的客户端会访问不同的键, 碰撞的情况一般都很少, 所以通常并不需要进行重试。

  • 乐观锁(Optimistic Lock):顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。如:WATCH 指令
  • 悲观锁(Pessimistic Lock):顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。如:Redis 实现的分布式锁

使用无参数的 UNWATCH 命令可以手动取消对所有键的监视。 对于一些需要改动多个键的事务,有时候程序需要同时对多个键进行加锁, 然后检查这些键的当前值是否符合程序的要求。 当值达不到要求时, 就可以使用 UNWATCH 命令来取消目前对键的监视, 中途放弃这个事务, 并等待事务的下次尝试。

WATCH 命令的实现原理

在每个代表数据库的 redis.h/redisDb 结构类型中, 都保存了一个 watched_keys 字典, 字典的键是这个数据库被监视的键, 而字典的值是一个链表, 链表中保存了所有监视这个键的客户端,如下图。

Redis设计与实现

WATCH 命令的作用, 就是将当前客户端与要监视的键在 watched_keys 中进行关联。

举个例子, 如果当前客户端为 client99 , 那么当客户端执行 WATCH key2 key3 时, 前面展示的 watched_keys 将被修改成这个样子:

图:Redis设计与实现

通过 watched_keys 字典, 如果程序想检查某个键是否被监视, 那么它只要检查字典中是否存在这个键即可; 如果程序要获取监视某个键的所有客户端, 那么只要取出键的值(一个链表), 然后对链表进行遍历即可。

WATCH 的触发

在任何对数据库键空间(key space)进行修改的命令成功执行之后 (比如 FLUSHDB、SET 、DEL、LPUSH、 SADD,诸如此类), multi.c/touchWatchedKey 函数都会被调用 —— 它检查数据库的 watched_keys 字典, 看是否有客户端在监视已经被命令修改的键, 如果有的话, 程序将所有监视这个/这些被修改键的客户端的 REDIS_DIRTY_CAS 选项打开:

图:Redis设计与实现

当客户端发送 EXEC 命令、触发事务执行时, 服务器会对客户端的状态进行检查:

  • 如果客户端的 CLIENT_DIRTY_CAS 选项已经被打开,那么说明被客户端监视的键至少有一个已经被修改了,事务的安全性已经被破坏。服务器会放弃执行这个事务,直接向客户端返回空回复,表示事务执行失败。
  • 如果 CLIENT_DIRTY_CAS 选项没有被打开,那么说明所有监视键都安全,服务器正式执行事务。
事务的 ACID 性质

在传统的关系式数据库中,常常用 ACID 性质来检验事务功能的安全性。Redis 事务保证了其中的一致性(C)和隔离性(I),但并不保证原子性(A)和持久性(D)。

原子性(Atomicity)

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

如果一个事务队列中的所有命令都被成功地执行,那么称这个事务执行成功。

另一方面,如果 Redis 服务器进程在执行事务的过程中被停止 —— 比如接到 KILL 信号、宿主机器停机,等等,那么事务执行失败。当事务失败时,Redis 也不会进行任何的重试或者回滚动作。

一致性(Consistency)

Redis 的一致性问题可以分为三部分来讨论:入队错误、执行错误、Redis 进程被终结。

入队错误

在命令入队的过程中,如果客户端向服务器发送了错误的命令,比如命令的参数数量不对,等等, 那么服务器将向客户端返回一个出错信息, 并且将客户端的事务状态设为 REDIS_DIRTY_EXEC

当客户端执行 EXEC 命令时, Redis 会拒绝执行状态为 REDIS_DIRTY_EXEC 的事务, 并返回失败信息。

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> set key
(error) ERR wrong number of arguments for 'set' command

redis 127.0.0.1:6379> EXISTS key
QUEUED

redis 127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

因此,带有不正确入队命令的事务不会被执行,也不会影响数据库的一致性。

执行错误

如果命令在事务执行的过程中发生错误,比如说,对一个不同类型的 key 执行了错误的操作, 那么 Redis 只会将错误包含在事务的结果中, 这不会引起事务中断或整个失败,不会影响已执行事务命令的结果,也不会影响后面要执行的事务命令, 所以它对事务的一致性也没有影响。

Redis 进程被终结

如果 Redis 服务器进程在执行事务的过程中被其他进程终结,或者被管理员强制杀死,那么根据 Redis 所使用的持久化模式,可能有以下情况出现:

  • 内存模式:如果 Redis 没有采取任何持久化机制,那么重启之后的数据库总是空白的,所以数据总是一致的。

  • RDB 模式:在执行事务时,Redis 不会中断事务去执行保存 RDB 的工作,只有在事务执行之后,保存 RDB 的工作才有可能开始。所以当 RDB 模式下的 Redis 服务器进程在事务中途被杀死时,事务内执行的命令,不管成功了多少,都不会被保存到 RDB 文件里。恢复数据库需要使用现有的 RDB 文件,而这个 RDB 文件的数据保存的是最近一次的数据库快照(snapshot),所以它的数据可能不是最新的,但只要 RDB 文件本身没有因为其他问题而出错,那么还原后的数据库就是一致的。

  • AOF 模式:因为保存 AOF 文件的工作在后台线程进行,所以即使是在事务执行的中途,保存 AOF 文件的工作也可以继续进行,因此,根据事务语句是否被写入并保存到 AOF 文件,有以下两种情况发生:

    1)如果事务语句未写入到 AOF 文件,或 AOF 未被 SYNC 调用保存到磁盘,那么当进程被杀死之后,Redis 可以根据最近一次成功保存到磁盘的 AOF 文件来还原数据库,只要 AOF 文件本身没有因为其他问题而出错,那么还原后的数据库总是一致的,但其中的数据不一定是最新的。

    2)如果事务的部分语句被写入到 AOF 文件,并且 AOF 文件被成功保存,那么不完整的事务执行信息就会遗留在 AOF 文件里,当重启 Redis 时,程序会检测到 AOF 文件并不完整,Redis 会退出,并报告错误。需要使用 redis-check-aof 工具将部分成功的事务命令移除之后,才能再次启动服务器。还原之后的数据总是一致的,而且数据也是最新的(直到事务执行之前为止)。

隔离性(Isolation)

Redis 事务在执行的过程中,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此,Redis 的事务是总是带有隔离性的。

持久性(Durability)

因为事务不过是用队列包裹起了一组 Redis 命令,并没有提供任何额外的持久性功能,所以事务的持久性由 Redis 所使用的持久化模式决定:

  • 在单纯的内存模式下,事务肯定是不持久的。

  • 在 RDB 模式下,服务器可能在事务执行之后、RDB 文件更新之前的这段时间失败,所以 RDB 模式下的 Redis 事务也是不持久的。

  • 在 AOF 的“总是 SYNC ”模式下,事务的每条命令在执行成功之后,都会立即调用 fsyncfdatasync 将事务数据写入到 AOF 文件。但是,这种保存是由后台线程进行的,主线程不会阻塞直到保存成功,所以从命令执行成功到数据保存到硬盘之间,还是有一段非常小的间隔,所以这种模式下的事务也是不持久的。

    其他 AOF 模式也和“总是 SYNC ”模式类似,所以它们都是不持久的。

小结
  • 事务提供了一种将多个命令打包,然后一次性、有序地执行的机制。
  • 事务在执行过程中不会被中断【即便中间命令报错】,所有事务命令执行完之后,事务才能结束。
  • 多个命令会被入队到事务队列中,然后按先进先出(FIFO)的顺序执行。
  • WATCH 命令的事务会将客户端和被监视的键在数据库的 watched_keys 字典中进行关联,当键被修改时,程序会将所有监视被修改键的客户端的 REDIS_DIRTY_CAS 选项打开。
  • 只有在客户端的 REDIS_DIRTY_CAS 选项未被打开时,才能执行事务,否则事务直接返回失败。
  • Redis 的事务保证了 ACID 中的一致性(C)和隔离性(I),但并不保证原子性(A)和持久性(D)。

Modules

布隆过滤器(RedisBloom)
什么是布隆过滤器

布隆过滤器是一种占用空间很小的数据结构,它由一个很长的二进制向量和一组Hash映射函数组成,它用于检索一个元素是否在一个集合中,空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

实现原理

假设我们有个集合A,A中有n个元素。利用k个哈希散列函数,将A中的每个元素映射到一个长度为a位的数组B中的不同位置上,这些位置上的二进制数均设置为1。如果待检查的元素,经过这k个哈希散列函数的映射后,发现其k个位置上的二进制数全部为1,这个元素很可能属于集合A,反之,一定不属于集合A

来看个简单例子吧,假设集合A有3个元素,分别为{d1,d2,d3}。有1个哈希函数 Hash1。现在将A的每个元素映射到长度为16位数组B。

img

我们现在把 d1 映射过来,假设 Hash1(d1) = 2,我们就把数组B中,下标为2的格子改成1,如下:

img

我们现在把 d2 也映射过来,假设 Hash1(d2) = 5,我们把数组B中,下标为5的格子也改成1,如下:

img

接着我们把 d3 也映射过来,假设 Hash1(d3) 也等于 2,它也是把下标为2的格子标1:

img

因此,我们要确认一个元素dn是否在集合A里,我们只要算出 Hash1(dn) 得到的索引下标,只要是0,那就表示这个元素不在集合A,如果索引下标是1呢?那该元素可能是A中的某一个元素。因为 d1 和 d3 得到的下标值,都可能是1,还可能是其他别的元素映射的;所以布隆过滤器存在这个缺点:可能存在hash碰撞导致的假阳性,判断存在误差。

如何减少这种误差呢?

  • 多搞几个哈希函数映射,降低哈希碰撞的概率
  • 同时增加B数组的bit长度,可以增大hash函数生成的数据的范围,也可以降低哈希碰撞的概率

我们又增加一个 Hash2 哈希映射函数,假设 Hash2(d1) = 6,Hash2(d3) = 8,它俩不就不冲突了嘛,如下:

img

如何选择哈希函数个数和布隆过滤器长度

很显然,过小的布隆过滤器很快所有的 bit 位均为 1,那么查询任何值都会返回“可能存在”,起不到过滤的目的了。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。

另外,哈希函数的个数也需要权衡,个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那我们的误报率会变高。

请添加图片描述

如何选择适合业务的 k 和 m 值呢,这里直接贴一个公式:

请添加图片描述

布隆过滤器应用

在实际工作中,布隆过滤器常见的应用场景如下:

  • 网页爬虫对 URL 去重,避免爬取相同的 URL 地址;
  • 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱;
  • Google Chrome 使用布隆过滤器识别恶意 URL;
  • Medium 使用布隆过滤器避免推荐给用户已经读过的文章;
  • Google BigTable,Apache HBbase 和 Apache Cassandra 使用布隆过滤器减少对不存在的行和列的查找。 除了上述的应用场景之外,布隆过滤器还有一个应用场景就是解决缓存穿透的问题。所谓的缓存穿透就是服务调用方每次都是查询不在缓存中的数据,这样每次服务调用都会到数据库中进行查询,如果这类请求比较多的话,就会导致数据库压力增大,这样缓存就失去了意义。

利用布隆过滤器我们可以预先把数据查询的主键,比如用户 ID 或文章 ID 缓存到过滤器中。当根据 ID 进行数据查询的时候,我们先判断该 ID 是否存在,若存在的话,则进行下一步处理。若不存在的话,直接返回,这样就不会触发后续的数据库查询。需要注意的是缓存穿透不能完全解决,我们只能将其控制在一个可以容忍的范围内。

简单使用

Github:https://github.com/RedisBloom/RedisBloom

wget https://github.com/RedisBloom/RedisBloom/archive/refs/tags/v2.2.9.zip
yum install unzip
unzip v2.2.9.zip
make
cp bloom.so /opt/middleware/redis6/
redis-server --loadmodule /opt/middleware/redis6/redisbloom.so

redis-cli
BF.ADD ooxx abc
BF.EXISTS ooxx abc
BF.EXISTS ooxx sdfsdf

CF.DEL

目前布隆过滤器已经有相应实现的开源类库啦,如Google的Guava类库,Twitter的 Algebird 类库,或者基于Redis 自带的 Bitmaps 自行实现设计也是可以的。

Redis的过期键的删除策略

可以通过以下命令设置key的有效期:

  • EXPIRE:设置过期时间【有效期/秒】
  • EXPIREAT:设置定时过期时间【时间戳/秒】
  • PERSIST:设置key永久有效

Redis keys过期有两种方式:

  • 被动式:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。

  • 主动式:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。(expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)

    具体来说,这是 Redis 每秒执行 10 次的操作:

    1. 从具有关联过期时间的密钥集中测试 20 个随机密钥。
    2. 删除所有发现过期的密钥。
    3. 如果超过 25% 的密钥过期,重复步奏1。

    这是一个平凡的概率算法,基本上的假设是,我们的样本是这个密钥控件,并且我们不断重复过期检测,直到过期的keys的百分百低于25%,这意味着,在任何给定的时刻,最多会清除1/4的过期keys

Redis的内存回收策略

当Redis被当做缓存来使用,当你新增数据时,让它自动地回收旧数据是件很方便的事情

maxmemory 指令用于配置Redis存储数据时指定限制的内存大小。通过redis.conf可以设置该指令,或者之后使用CONFIG SET命令来进行运行时配置。

例如为了配置内存限制为100mb,以下的指令可以放在 redis.conf 文件中。

maxmemory 100mb

设置 maxmemory 为0代表没有内存限制。对于64位的系统这是个默认值,对于32位的系统默认内存限制为3GB。

当Redis的内存使用达到 maxmemory 配置的大小时,Redis会使用 maxmemory-policy 配置的行为进行内存回收,其回收策略如下:

  • noeviction:当内存不足以容纳新写入数据时,新写入操作会报错【默认】。

  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,优先移除会更早过期的key。

  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。

  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。

  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。

  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。

  • allkeys-lfu:当内存不足以容纳新写入数据时,在键空间中,删除使用频率最少的key。

  • volatile-lfu:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,删除使用频率最少的key。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值