>什么是 Redis 事务
Redis 事务是一组命令的有序集合,在执行时按顺序依次执行,不会被其他客户端的命令插入打断。事务通过 MULTI、EXEC、DISCARD 和 WATCH 四个命令实现,适合需要保证操作原子性的场景。
与关系型数据库不同,Redis 事务不支持回滚(rollback),如果某个命令执行失败,其余命令仍会继续执行。
>CentOS 安装 Redis
>通过 Yum 安装
>
启用 EPEL 仓库
sudo yum install -y epel-release
>安装 Redis
sudo yum install -y redis
>启动并设置开机自启
sudo systemctl start redis
sudo systemctl enable redis
通过源码编译安装
>
安装编译依赖
sudo yum groupinstall -y "Development Tools"
sudo yum install -y tcl
>下载并编译
wget https://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
make test
sudo make install
Redis 事务核心命令
| 命令 | 功能说明 |
|------|---------|
| MULTI | 标记事务开始,之后所有命令进入队列 |
| EXEC | 执行事务队列中的所有命令 |
| DISCARD | 放弃事务,清空命令队列 |
| WATCH | 监视一个或多个键,若在 EXEC 前被修改则事务中止 |
>事务基本用法
>标准事务流程
>127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET account:A 1000
QUEUED
127.0.0.1:6379> SET account:B 500
QUEUED
127.0.0.1:6379> INCRBY account:A -200
QUEUED
127.0.0.1:6379> INCRBY account:B 200
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) (integer) 800
4) (integer) 700
进入 MULTI 后,命令不会立即执行,而是返回 QUEUED。调用 EXEC 后所有命令一次性按序执行。
>取消事务
>127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key1 "value1"
QUEUED
127.0.0.1:6379> DISCARD
OK
DISCARD 会清空队列并退出事务状态,所有排队的命令都不会执行。
>WATCH 实现乐观锁
WATCH 是 Redis 事务实现并发控制的关键命令,用于监视一个或多个键。如果在 WATCH 之后、EXEC 之前,被监视的键被其他客户端修改,事务将自动取消。
>典型场景:安全转账
>
客户端 A:监视账户余额
127.0.0.1:6379> WATCH account:A
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY account:A 300
QUEUED
127.0.0.1:6379> INCRBY account:B 300
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 500
2) (integer) 1000
如果在此期间另一个客户端修改了 account:A,EXEC 将返回 nil,事务不会执行。
>WATCH 使用注意事项
>
WATCH 必须在 MULTI 之前调用
EXEC 执行后会自动取消所有监视,无需手动 UNWATCH
DISCARD 也会取消监视
- 可同时监视多个键:
WATCH key1 key2 key3
>在 Python 中使用 Redis 事务
>使用 pipeline 模拟事务
>import redis
r = redis.Redis(host='localhost', port=6379, db=0)
>方式一:pipeline 事务模式
pipe = r.pipeline(transaction=True)
pipe.set('account:A', 1000)
pipe.set('account:B', 500)
pipe.decrby('account:A', 200)
pipe.incrby('account:B', 200)
results = pipe.execute()
print(results) # [True, True, 800, 700]
结合 WATCH 实现乐观锁
>import redis
r = redis.Redis(host='localhost', port=6379, db=0)
def safe_transfer(from_key, to_key, amount, max_retries=5):
for attempt in range(max_retries):
try:
r.watch(from_key)
balance = int(r.get(from_key) or 0)
if balance < amount:
r.unwatch()
return False
pipe = r.pipeline(transaction=True)
pipe.decrby(from_key, amount)
pipe.incrby(to_key, amount)
results = pipe.execute()
return True
except redis.WatchError:
print(f"重试第 {attempt + 1} 次...")
continue
return False
safe_transfer('account:A', 'account:B', 200)
Redis 配置优化建议
>修改 redis.conf
>sudo vi /etc/redis/redis.conf
关键配置项:
>
绑定地址(生产环境不要用 0.0.0.0)
bind 127.0.0.1
>设置密码
requirepass your_strong_password
>关闭危险命令
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command CONFIG ""
>超时设置(秒),客户端空闲超过此时间断开
timeout 300
>TCP keepalive
tcp-keepalive 60
重启使配置生效
>sudo systemctl restart redis
常见问题与排查
>事务中命令出错怎么办
语法错误:如果入队时就有语法错误,EXEC 会拒绝执行整个事务
运行时错误:如果某个命令类型不匹配(如对字符串执行 INCR),该命令失败但其余命令继续执行
>127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET str_key "hello"
QUEUED
127.0.0.1:6379> INCR str_key
QUEUED
127.0.0.1:6379> SET another_key "world"
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
连接超时排查
>
检查 Redis 是否运行
sudo systemctl status redis
>检查端口监听
ss -tlnp | grep 6379
>测试连接
redis-cli ping
内存不足
>
查看内存使用
redis-cli info memory
>设置最大内存和淘汰策略
在 redis.conf 中添加:
maxmemory 512mb
maxmemory-policy allkeys-lru
总结
Redis 事务通过 MULTI/EXEC/DISCARD/WATCH 四个命令实现了简单但实用的原子操作机制。在 CentOS 环境下,配置好 Redis 服务后即可直接使用。需要注意的核心要点:
事务不保证回滚,需在设计时考虑失败场景
使用 WATCH 实现乐观锁,适合高并发场景
生产环境务必设置密码、绑定地址、禁用危险命令
在编程语言中通过 pipeline 使用事务更加便捷安全