穿越来找茬
35.39MB · 2025-09-13
Redis 支持事务,但它的事务与 MSQL中的事务有所不同,MSOL中的事务主要支持 ACID 的特性,而 Redis中的事务主要保证的是多个命令执行的原子性,即所有的命令在一个原子操作中执行,不会被打断。还有一个很重要的点,就是 MySQL 中的事务是支持回滚的,而 Redis 中的事务是不支持回滚的。
Redis事务是指将多条命令加入队列,一次批量执行多条命令,每条命令会按顺序执行,事务执行过程中不会被其他客户端发来的命令所打断。也就是说,Redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。
Redis事务和关系型数据库的事务不太一样,它不保证原子性,也没有隔离级别的概念。
事务不保证原子性,但是Redis命令本身是原子性的
WATCH命令
WATCH
命令可以监控一个或多个键,一旦其中有一个键被修改,之后的事务就不会执行(类似于乐观锁)。执行EXEC
命令之后,就会自动取消监控。
127.0.0.1:6379> watch nameOK127.0.0.1:6379> set name 1OK127.0.0.1:6379> multiOK127.0.0.1:6379> set name 2QUEUED127.0.0.1:6379> set gender 1QUEUED127.0.0.1:6379> exec(nil)127.0.0.1:6379> get gender(nil)
比如上面的代码中:
watch name
开启了对name
这个key
的监控name
的值name
和gender
的值EXEC
命令进提交事务get gender
发现不存在,即事务a没有执行使用UNWATCH
可以取消WATCH
命令对key
的监控,所有监控锁将会被取消。
Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此,Redis 的事务是总是带有隔离性的。
Redis单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。
Redis 的 Lua 脚本功能允许用户在 Redis 服务器端执行自定义的 Lua 脚本,以实现原子操作和复杂逻辑。其核心点包括:
例如常见基于 Redis 实现分布式锁就需要结合 lua 脚本来实现。
lua 本身是不具备原子性的,但由于 Redis的命令是单线程执行的,它会把整个|ua 脚本作为一个命令执行,会阻塞其间接受到的其他命令,这就保证了 lua 脚本的原子性。
详细可以查看:
持久化就是把内存的数据写到磁盘中,防止服务宕机导致内存数据丢失。
Redis支持两种方式的持久化,一种是RDB
的方式,一种是AOF
的方式。前者会根据指定的规则定时将内存中的数据存储在硬盘上,而后者在每次执行完命令后将命令记录下来。Redis 4.0 新增了 RDB 和 AOF 的混合持久化机制,一般将两者结合使用。
RDB
是 Redis 默认的持久化方案。RDB持久化时会将内存中的数据写入到磁盘中,在指定目录下生成一个dump.rdb
文件。Redis 重启会加载dump.rdb
文件恢复数据。
bgsave
是主流的触发 RDB 持久化的方式,执行过程如下:
BGSAVE
命令BGSAVE
命令直接返回。fork
操作创建子进程,fork操作过程中父进程会阻塞。fork
完成后,父进程继续接收并处理客户端的请求,而子进程开始将内存中的数据写进硬盘的临时文件;Redis启动时会读取RDB快照文件,将数据从硬盘载入内存。通过 RDB 方式的持久化,一旦Redis异常退出,就会丢失最近一次持久化以后更改的数据。
触发 RDB 持久化的方式:
手动触发:用户执行SAVE
或BGSAVE
命令。SAVE
命令执行快照的过程会阻塞所有客户端的请求,应避免在生产环境使用此命令。BGSAVE
命令可以在后台异步进行快照操作,快照的同时服务器还可以继续响应客户端的请求,因此需要手动执行快照时推荐使用BGSAVE
命令。
被动触发:
SAVE 100 10
,100秒内至少有10个键被修改则进行快照。BGSAVE
生成 RDB 文件并发送给从节点。shutdown
命令时,如果没有开启 AOF 持久化功能则自动执行·BGSAVE·。优点:
缺点:
BGSAVE
每次运行都要执行fork
操作创建子进程,属于重量级操作,频繁执行成本比较高。在 Redis 生成 RDB文件时是异步的(使用 bgsave 命令),采用了fork子进程的方式来进行快照操作,生成 RD8文件的过程由子进程执行,主进程维续处理客户端清求,所以可以保证 Redis在生成快照的过程中依然对外提供服务,不会影响正常请求。
当然可以。主进程会正常处理客户端的请求,进行数据的修改,但数据被修改还叫快照吗?
此时就运用了写时复制的技术。当主进程 fork 出一个子进程后,并不会把主进程的所有内存数据重新复制一份给子进程,而是让主进程和子进程共享相同的内存页面。
底层的实现仅仅复制了页表,但映射的物理内存还是同一个。这样做可以加快 fork 的速度,减少性能损耗(fork会阻塞主进程)。
AOF(append only file)持久化:以独立日志的方式记录每次写命令,Redis重启时会重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,AOF 是Redis持久化的主流方式。
默认情况下Redis没有开启AOF方式的持久化,可以通过appendonly
参数启用:appendonly yes
。开启AOF方式持久化后每执行一条写命令,Redis就会将该命令写进aof_buf
缓冲区,AOF缓冲区根据对应的策略向硬盘做同步操作。
默认情况下系统每30秒会执行一次同步操作。为了防止缓冲区数据丢失,可以在Redis写入AOF文件后主动要求系统将缓冲区数据同步到硬盘上。可以通过appendfsync
参数设置同步的时机。
appendfsync always //每次写入aof文件都会执行同步,最安全最慢,不建议配置appendfsync everysec //既保证性能也保证安全,建议配置appendfsync no //由操作系统决定何时进行同步操作
接下来看一下 AOF 持久化执行流程:
优点:
fsync
操作,如果Redis进程挂掉,最多丢失1秒的数据。append-only
的模式写入,所以没有磁盘寻址的开销,写入性能非常高。缺点:
主进程
执行的,总是调用fsync函数;Everysec异步执行,不影响主线程;No则redis不控制写回,最终交给操作系统决定何时写回;不影响主线程。子进程
来做,此时Redis主线程还可以继续处理操作命令。如果同时存在RDB文件和AOF文件,Redis会优先使用AOF文件进行数据恢复。
RDB 比 AOF 的数据恢复速度快,但是快照的频率不好把握:
因此可以使用混合持久化,混合持久化就是混合使用 AOF 日志和RDB
混合持久化工作在 AOF日志重写过程中:
会把 Redis 的持久化数据,以 RDB 的格式写入到 AOF 文件的开头,之后写时复制时修改数据再以 AOF 的格式化追加的文件的末尾,写入完成后再新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。
也就是说,使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据。
优点:
缺点:
本文来自在线网站:seven的菜鸟成长之路,作者:seven,转载请注明原文链接:www.seven97.top