Redis 学习-中
三、Redis 事务
3.1、Transactions 简介
- MULTI、EXEC、DISCARD 和 WATCH 是 Redis 中事务的基础,它们允许在一个步骤中执行一组命令。
- 事务中的所有命令都会被序列化并按照 顺序执行 ,这保证了命令作为单个隔离操作执行。
- 要么处理所有命令,要么不处理任何命令,因此 Redis 事务也是原子的,EXEC 命令会触发事务中所有命令的执行。
- Redis 的单条命令是保证原子性的,但是 Redis 事务不能保证原子性。
- Redis 事务没有隔离级别概念。
- 一次性、顺序性、排他性。
3.2、Redis 用法
1、MULTI(开启事务)
相反,调用DISCARD将刷新事务队列并退出事务。
- 当 Redis 连接在MULTI请求的上下文中时,所有命令都将使用字符串
QUEUED
进行回复。
> MULTIOK> INCR fooQUEUED> INCR barQUEUED> EXEC1) (integer) 12) (integer) 1
2、EXEC (执行事务)
-
所以事务中的命令在加入时都没有被执行,直到提交时才会开始执行(Exec)一次性完成。
-
事务执行期间,可能会遇到两种命令错误:
-
- 代码语法错误(编译时异常),所有命令都不会执行
- 代码逻辑错误(运行时异常), 其他命令可以正常执行 ---- 所以不保证事务原子性
-
Redis 不支持回滚
-
- Redis 内部简化且速度更快,因为它不需要回滚的能力
- Redis 回滚不会使您免于编程错误,命令失败所需的错误不太可能进入生产环境
3、DISCARD(丢弃命令队列)
- DISCARD可用于中止事务。在这种情况下,不执行任何命令,连接状态恢复正常。
4、WATCH(监控)
- 用于为 Redis 事务提供检查和设置 (CAS) 行为。
WATCH
ed keys 被监控以检测针对它们的更改。如果在执行 EXEC命令之前至少修改了一个监视键,则整个事务中止,并且EXEC返回Null 回复以通知事务失败。- 使用
watch key
监控指定数据,相当于乐观锁加锁。 - 注意:每次提交执行exec后都会自动释放锁,不管是否成功
3.3、Redis 脚本和事务
- Redis 脚本在定义上是事务性的,所以你可以用 Redis 事务做的所有事情,你也可以用脚本做,通常脚本会更简单更快。
四、Redis 持久化
4.1、Redis 持久化概念
-
https://www.cnblogs.com/xiaoxi/p/7065328.html(持久化详细介绍)
Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存储在内存中的数据将会丢失,在很多情况下是无法容忍这样的事情的。所以,我们需要将内存中的数据持久化!典型的需要持久化数据的场景如下:
-
将Redis作为数据库使用;
-
将Redis作为缓存服务器使用,但是缓存miss后会对性能造成很大影响,所有缓存同时失效时会造成服务雪崩,无法响应。
-
Redis支持两种数据持久化方式:RDB方式和AOF方式。前者会根据配置的规则定时将内存中的数据持久化到硬盘上,后者则是在每次执行写命令之后将命令记录下来。两种持久化方式可以单独使用,但是通常会将两者结合使用。
4.2、Redis 持久化类型
- RDB(Redis 数据库):RDB 持久性以指定的时间间隔执行数据集的时间点快照。
- AOF(Append Only File):AOF 持久化记录服务器接收到的每个写操作,在服务器启动时再次播放,重建原始数据集。命令使用与 Redis 协议本身相同的格式以仅附加方式记录。当日志变得太大时,Redis 能够在后台重写日志。
- 无持久性:如果您愿意,您可以完全禁用持久性,如果您希望您的数据只要服务器正在运行就存在。
- RDB + AOF:可以在同一个实例中结合 AOF 和 RDB。请注意,在这种情况下,当 Redis 重新启动时,AOF 文件将用于重建原始数据集,因为它保证是最完整的。
4.3、Redis 之 RDB
1、什么是 RDB?
- 在指定时间间隔后,将内存中的数据集快照写入数据库 ;在恢复时候,直接读取快照文件,进行数据的恢复 ;
- 默认情况下, Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。文件名可以在配置文件中进行自定义。
2、工作原理
-
在进行 RDB 的时候,redis 的主线程是不会做 io 操作的,主线程会 fork 一个子线程来完成该操作;
-
- Redis 调用forks。同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时 RDB 文件中。
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
- 这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益(因为是使用子进程进行写操作,而父进程依然可以接收来自客户端的请求。)
3、触发机制
a、根据配置规则进行自动快照
-
Redis允许用户自定义快照条件,当满足条件时自动执行快照。缺省情况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb,此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开redis.windows.conf文件之后,我们搜索save,可以看到下面的配置信息:
- 每个快照条件独占一行,他们之间是或(||)关系,只要满足任何一个就进行快照。上面配置save后的第一个参数T是时间,单位是秒,第二个参数M是更改的键的个数,含义是:当时间T内被更改的键的个数大于M时,自动进行快照。比如
save 900 1
的含义是15分钟内(900s)被更改的键的个数大于1时,自动进行快照操作。
b、执行SAVE或BGSAVE命令
- 使用
save
命令,会立刻对当前内存中的数据进行持久化 ,但是会阻塞,也就是不接受其他操作了; - 由于 save 命令是同步命令,会占用Redis的主进程。若Redis数据非常多时,save命令执行速度会非常慢,阻塞所有客户端的请求。
- BGSAVE命令: 从命令名字就能看出来,这个命令与SAVE命令的区别就在于该命令的快照操作是在后台异步进行的,进行快照操作的同时还能处理来自客户端的请求。执行BGSAVE命令后Redis会马上返回OK表示开始进行快照操作,如果想知道快照操作是否已经完成,可以使用LASTSAVE命令返回最近一次成功执行快照的时间,返回结果是一个Unix时间戳。
c、执行FLUSHALL命令
- 当执行FLUSHALL命令时,Redis会清除数据库中的所有数据。需要注意的是:不论清空数据库的过程是否触发了自动快照的条件,只要自动快照条件不为空,Redis就会执行一次快照操作,当没有定义自动快照条件时,执行FLUSHALL命令不会进行快照操作。
d、执行复制
- 当设置了主从模式时,Redis会在复制初始化时进行自动快照。
4、常用配置
- Redis会将数据集的快照dump到dump.rdb文件中。此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件之后,我们搜索save,可以看到下面的配置信息:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
4.4、Redis 之 AOF
1、什么是 AOF
- 以日志的形式来记录每个写的操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
- AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令.
2、常用配置
- 在Redis的配置文件中存在三种同步方式,它们分别是:
appendfsync always #每次有数据修改发生时都会写入AOF文件。appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。appendfsync no #从不同步。高效但是数据不会被持久化。
4.5、RDB 和 AOF 的优/劣
1、RDB存在哪些优势呢?
1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。
2、RDB又存在哪些劣势呢?
1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。
3、AOF的优势有哪些呢?
1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。
2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。
3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。
4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。
4、AOF的劣势有哪些呢?
1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。
- 二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。
RDB | AOF | |
---|---|---|
启动优先级 | 低 | 高 |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 丢数据 | 根据策略决定 |
五、Redis 淘汰策略
5.1、Redis Key 的相关设置
1、Redis key 过期时间设置
- EXPIRE
:表示将键 key 的生存时间设置为 ttl 秒。 - PEXPIRE
:表示将键 key 的生存时间设置为 ttl 毫秒。 - EXPIREAT
:表示将键 key 的生存时间设置为 timestamp 所指定的秒数时间戳。 - PEXPIREAT
:表示将键 key 的生存时间设置为 timestamp 所指定的毫秒数时间戳。 - 在Redis内部实现中,前面三个设置过期时间的命令最后都会转换成最后一个PEXPIREAT 命令来完成。
2、移除 key 的过期时间
- PERSIST
:表示将 key 的过期时间移除。
3、返回 key 的剩余生存时间
- TTL
:以秒的单位返回 key 的剩余生存时间。 - PTTL
:以毫秒的单位返回 key 的剩余生存时间。 - 在Redis内部,每当我们设置一个键的过期时间时,Redis就会将该键带上过期时间存放到一个过期字典中。当我们查询一个键时,Redis便首先检查该键是否存在过期字典中,如果存在,那就获取其过期时间。然后将过期时间和当前系统时间进行比对,比系统时间大,那就没有过期;反之判定该键过期。
5.2、Redis 的过期策略
- Redis的过期删除策略就是:惰性删除和定期删除两种策略配合使用。
1、定期删除
- 指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。
- 优势:对 内存 友好,对定时的清理过期 key,内存得到释放。
- 劣势:对 CPU 不友好,并且过期 key 随意删除没删掉,有可能被获取到,不利于业务。
2、惰性删除
- 在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。 并不是key到时间就被删除掉,而是你查询这个key的时候,redis再懒惰的检查一下
- 优势:对 CPU 友好,过期的 key 不可能被获取到。
- 劣势:对 内存 不友好,内存不能得到及时释放。
5.3、Redis 的内存淘汰策略
1、设置 Redis 最大内存
- 在配置文件redis.conf 中,可以通过参数 maxmemory
来设定最大内存。 - 不设定该参数默认是无限制的,但是通常会设定其为物理内存的四分之三。
2、设置淘汰内存方式
当现有内存大于 maxmemory 时,便会触发redis主动淘汰内存方式,通过设置 maxmemory-policy ,有如下几种淘汰方式:
- noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
- allkeys-lru:当内存不足以容纳新写入数据时,在 全局 key 中移除最近最少使用的 key (常用)。
- allkeys-random:当内存不足以容纳新写入数据时,在 全局 key中随机移除某个 key 。
- volatile-lru:当内存不足以容纳新写入数据时,在 设置了过期时间 的 key 中,移除最近最少使用的 key 。
- volatile-random:当内存不足以容纳新写入数据时,在 设置了过期时间 的 key 中,随机移除某个 key 。
- volatile-ttl:当内存不足以容纳新写入数据时,在 设置了过期时间 的 key 中,优先移除临近过期的 key 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)