Redis作为一款非关系型数据库,自然也拥有事务的支持,关系型数据库例如MySQL的事务具有ACID这四大基本特征,即Atomicity原子性,Consistency一致性,Isolation隔离性,Durability持久性。
1.0 事务队列
Redis指令在multi创建事务之后,会被放入事务队列中,在exec之时会将指令依次从事务队列中提取出来执行,在discard之时会将事务队列抛弃。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YZhcYlLv-1572500173064)(http://note.youdao.com/yws/res/543/4B0F8FC9000A46839DC393E27E58C175)]
1.1 Redis事务基本用法
1.开启事务:
multi命令用于开启事务,在开启事务之后,事务将不会被自动提交
127.0.0.1:6371> set arong test
OK
127.0.0.1:6371> multi
OK
127.0.0.1:6371> set arong test1
QUEUED
127.0.0.1:6371> set arong test2
QUEUED
127.0.0.1:6371> exec
1) OK
2) OK
127.0.0.1:6371> get arong
"test2"
2.提交事务
exec命令用于提交事务,提交的事务中若有失败也不会将全部指令都回滚掉,而是继续执行其他语句,所以Redis的事务不具备原子性,而只是提供了隔离性机制。
127.0.0.1:6371> set arong test
OK
127.0.0.1:6371> multi
OK
127.0.0.1:6371> rpush arong test1
QUEUED
127.0.0.1:6371> set arong test2
QUEUED
127.0.0.1:6371> exec
1) (error) WRONGTYPE Operation against a key holding the wrong kind of value
2) OK
127.0.0.1:6371> get arong
"test2"
3.回滚事务
discard命令用于回滚事务,回滚事务会将所有的指令抛弃。
127.0.0.1:6371> set arong test
OK
127.0.0.1:6371> multi
OK
127.0.0.1:6371> set arong test1
QUEUED
127.0.0.1:6371> set arong test2
QUEUED
127.0.0.1:6371> discard
OK
127.0.0.1:6371> get arong
"test"
1.2 watch命令
watch命令用于监控某个key,需要在开启事务前使用,它的作用是当事务开启后,若在提交事务时发现该key已经被更改过,那么所提交的指令全部回滚失效,否则正常提交。其实watch命令的实质是CAS算法,即比较后再决定是否是正确的预期。用一个给银行存款加倍的程序来演示一下:
public static int doubleAccount(Jedis jedis, String accountId) {
while (true) {
//监听该accountId的值
jedis.watch(accountId);
int money = Integer.parseInt(jedis.get(accountId));
//开启事务
Transaction tx = jedis.multi();
//将钱款*2
tx.set(accountId, String.valueOf(money * 2));
//提交事务
List<Object> res = tx.exec();
if (res != null) {
//提交事务成功
break;
}
}
//返回当前余额
return Integer.parseInt(jedis.get(accountId));
}
1.3 为什么Redis事务不支持原子操作?
1.出于对性能的考虑
2.作者认为Redis事务应该在开发业务层面考虑
本文深入探讨Redis事务的基本用法,包括multi、exec和discard命令的使用,解释了watch命令如何提供CAS机制确保数据一致性,以及为何Redis事务不支持原子操作的原因。
278

被折叠的 条评论
为什么被折叠?



