Redis-事务

1.事务的定义

百度百科:数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始事务结束之间执行的全部数据库操作组成。
作者理解:事务是将多条命令放到一起执行,要么都执行,要么都不执行。事务的执行要保证四大特性:原子性,一致性,隔离性,持久性。

2.Redis事务的特性

  1. 原子性:Redis的原子性只能保证事务中的命令一起执行,和传统mysql事务不同的是,Redis不支持回滚,在执行EXEC命令时,如果Redis事务中某条命令执行失败,其后的命令仍然会被执行没有回滚
  2. 隔离性:因为Redis是单线程处理任务,所以不会和其他的事务并发执行,天生具备隔离性。
  3. 持久性 :Redis的持久化(AOF,RDB)可以保证数据的持久性。
  4. 一致性:Redis不支持一致性,一致性是事务执行前后都有数据的一致,而Redis不支持回滚。

3.事务的错误处理

3.1简单说明

Redis在开启事务后会将接下来的命令先加入到队列当中,在事务提交时统一按顺序依次执行。所以,事务中命令出错就会在入队时执行时

3.2入队时产生的错误

语法错误,2.6.5之前会执行已经成功入队的命令,2.6.5及之后版本会自动丢弃整个事务。

6.2.5版本演示
在这里插入图片描述在这里插入图片描述

3.3执行时产生的错误

命令与数据类型不匹配,redis会依次执行事务中正确的命令
在这里插入图片描述

4.Redis为什么不支持回滚操作

分析Redis事务出错情况可知,无论是入队期间的错误还是执行期间的错误,都是能在程序员编写代码时避免的错误,例如,如果查询将键增加 2 而不是 1,或者增加了错误的键,则回滚机制无法提供帮助。所以,Redis并没有支持回滚操作,并且不支持回滚功能,也使得Redis在事务上可以保持简洁和快速。

5.事务相关的一些命令

MULTI:开启事务
EXEC:提交事务,如果有监视键,执行EXEC后也会取消监视。
DESCARD:手动取消事务
WATCH:监控某个或某些键,用于为 Redis 事务提供检查和设置 (CAS) 行为。如果在执行 EXEC命令之前至少修改了一个监视键,则整个事务中止,并且EXEC返回Null 回复以通知事务失败。
UNWATCH:取消监视。

6.WATCH原理

watch是相当于乐观锁,为监视的键加上版本号。在开启事务时,就为监听的键加上版本号,如果事务中有监视键,在执行事务的时候会再次对比监视键的版本号,如果版本号不匹配则会取消整个事务,返回(nul)。

不知道你是否有这个疑问?

Redis是单线程处理执行命令的,怎么可能监视键的版本号会不同呢,也就是为什么会出现访问冲突呢?
没错,Redis是单线程处理,但是一旦开启事务,Redis的命令不是直接执行,而是先放到队列,在执行。也就是确认某个监视键的版本号是在开始事务时,在这个事务执行前,有可能其他的命令已经修改了这个监视键,从而版本号发生改变,这是当事务提交就不会执行这个事务了。

7.WATCH(监视)用法

  1. 监视k1
  2. 先开启上图的事务,在开启下图的事务
  3. 写好中间命令
  4. 先提交上图事务,在提交下图事务
    在这里插入图片描述
    在这里插入图片描述
    分析:因为上下图同时监视k1,在上图未提交前下图开启了事务,此时两图对k1的版本号相同。
    在上图提交事务后,k1的版本号就会加1,
    之后提交下图事务,对比版本号发现不对,则取消整个事务。所以keys *中不会有k4、k5。
<think> 我们正在讨论的是Redis-Shake工具,用户之前遇到了"CROSSSLOT"错误,但现在的问题是如何在Redis-Shake中关闭事务。 根据Redis-Shake的文档和配置,我们可以通过设置配置文件中的参数来关闭事务(即不使用事务模式)。 在Redis-Shake中,事务通常用于保证数据同步的原子性,但某些情况下可能需要关闭,比如目标Redis不支持事务,或者为了性能考虑。 如何关闭事务? 在Redis-Shake的配置文件中,有一个关键的参数`rewrite`,它控制着是否重写命令。当`rewrite`设置为`true`时,Redis-Shake会将命令拆分为单命令执行,这样就不会使用MULTI/EXEC事务块。因此,设置`rewrite=true`可以间接达到关闭事务的效果。 另外,还有一个参数`target.db`,如果设置`target.db=-1`,则不会使用SELECT命令,但这不是直接关闭事务,而是避免切换数据库事务的关闭主要还是通过`rewrite`参数。 此外,在同步(sync)模式下,Redis-Shake默认会使用pipeline来发送命令,而pipeline中是可以包含多个命令的。如果我们将pipeline的大小设置为1,那么每个命令单独发送,这样就不会有事务效果。但是,设置`rewrite=true`已经可以达到拆分命令的目的。 因此,具体步骤如下: 1. 编辑Redis-Shake的配置文件(例如:redis-shake.conf)。 2. 找到或添加`rewrite`参数,并将其设置为`true`: ```ini rewrite = true ``` 3. 如果需要,也可以调整`pipeline`参数,将其设置为1,这样每个命令都会单独发送,但这样可能会降低性能,通常`rewrite=true`已经足够。 注意:在`rewrite=true`模式下,Redis-Shake会将所有命令拆分为单命令执行,包括原本可能在一个事务块中的命令(例如MULTI...EXEC中的命令)。因此,这实际上就关闭了事务。 但是,需要注意的是,关闭事务可能会影响数据一致性。在没有事务的情况下,如果同步过程中出现故障,可能会导致部分命令被执行而部分没有执行。因此,在不需要严格事务保证的场景下才考虑关闭事务。 另外,如果目标Redis是集群模式,那么使用`rewrite=true`也是解决跨槽错误的一种方法,因为它会将多键命令拆分成单键命令,从而避免跨槽错误。 总结:关闭事务的方法是设置`rewrite = true`。 下面给出配置文件的示例: ```ini # redis-shake.conf source.type: cluster source.address: <source_redis_cluster_address> target.type: cluster target.address: <target_redis_cluster_address> rewrite = true # 关闭事务(通过命令重写,拆分成单命令) ``` 注意:在集群模式下,目标Redis集群可能要求命令中的键在同一个槽,而`rewrite=true`可以避免跨槽问题,同时也就关闭了事务。 如果用户是为了解决跨槽问题而关闭事务,那么同时还需要确保其他配置正确,例如集群模式参数`--cluster=1`(在启动命令中指定)或者配置文件中的`cluster=true`(根据版本不同,配置方式可能略有差异)。 因此,在启动Redis-Shake时,可以这样写: ```bash ./redis-shake -type=sync -conf=redis-shake.conf --cluster=1 ``` 或者,在配置文件中设置`cluster=true`(如果版本支持): ```ini cluster = true ``` 这样,Redis-Shake就会以集群感知模式运行,并且通过重写命令(关闭事务)来避免跨槽错误。 最后,生成相关问题: </think> ### Redis-Shake 关闭事务的方法 在 Redis-Shake 中关闭事务功能,主要通过以下两种方法实现: #### 1. **配置文件修改(推荐)** 在配置文件中添加 `rewrite = true` 参数,这将强制 Redis-Shake 将所有命令拆解为单键操作,从而绕过事务机制: ```ini # redis-shake.conf rewrite = true # 关闭事务支持 ``` 此配置会实现: - 自动拆解 MULTI/EXEC 事务块为单命令[^1] - 禁用批量操作的事务保证 - 规避 Redis 集群的跨槽位限制 #### 2. **启动参数设置** 通过命令行添加 `--rewrite=1` 参数实现相同效果: ```bash ./redis-shake.linux -type=sync --rewrite=1 -conf=redis-shake.conf ``` ### ⚠️ 注意事项 1. **数据一致性影响** 关闭事务后: - 批量操作不再具有原子性保证 - 迁移过程中断可能导致部分数据不一致 - 需通过 `target.db=0` 明确指定集群仅用 db0[^2] 2. **性能权衡** | 模式 | 吞吐量 | 原子性 | 集群兼容性 | |---|---|---|---| | 事务开启 | 高 ✅ | 强 ✅ | 差 ❌ | | 事务关闭 | 中 ⚠️ | 弱 ❌ | 优 ✅ | 3. **替代方案建议** 若需保证事务性,可改用 Redis 原生迁移命令: ```bash redis-cli --cluster import <target_host>:<port> \ --cluster-from <source_host>:<port> \ --cluster-copy --cluster-replace ``` > **操作建议**:在测试环境验证 `rewrite = true` 的配置后,再在生产环境使用,并通过 `target.password_raw` 配置密码保证安全性[^3]。 [^1]: `rewrite=true` 强制命令拆解为单键操作 [^2]: 集群模式仅支持 db0 数据库 [^3]: 生产环境必须配置密码认证
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长不大的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值