redis-乐观锁与事务

一、乐观锁
先表明态度,乐观锁并不是一个好的实现方式!
在mysql中,我们一般通过给数据表额外建一个version字段,读的时候读出verson,更新的时候 v2 = versin+1,语句为

update xxx set xxx=xxx, version = version + 1 where id = xxx and version < v2;

只要有人在我前面更新了,我就会更新失败。然后直接响应给客户端错误吗?显然不能,在大并发的情况下,难道要客户一次次的手动提交吗?所以,我们只能替用户去循环尝试更新,让用户多等待一会,当然要设置循环次数或者时间。而且,虽然更新失败了,但是依然操作了数据库,而且是循环操作,更加使脆弱的mysql雪上加霜。那么,乐观锁能保证数据安全吗?可以的,因为在更新version的时候使用的是自增而不是赋值。

二、redis事务
虽然redis是单线程的,但是使用事务的时候,事务块会被放入事务队列中,直到调用exec命令,此时事务块作为一个原子插入到主执行队列中,虽然在执行事务块的时候是单线程的不存在并发,但是在构成事务块的过程中主线程同时执行着其他命令,是并行的,所以总的来看,事务不能保证数据的安全性。另外,redis事务不具备一致性,没有回滚机制。

示例1:
	multi
	set name rao
	set age 12
	set score 100
	exec

示例2:
	multi
	set name rao
	set age 13
	incr name
	exec
	get age

报错但没有回滚处理!!!!

exec返回以个数组,就是所有命令依次的结果。

当在构造事务的过程中想要取消事务,可使用discard命令

三、redis事务加乐观锁
既然存在并行的情况,那么数据安全就没法保障,所以,必须加个锁来保证事务过程中key的值不被改变。
watch:监视一个(或多个) key的版本变化 ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
在执行exec的时候,redis会去检查你watch的key。如果版本发生变化,就不执行。
如果watch了一个有过期时间的,且在exec之前刚好过期了,那么事务依然会执行。
当执行exec后,就会unwatch这些key;当客户端断开,也会unwatch这些key。

示例1:
	watch name age score
	multi
	set name rao
	set age 12
	set score 100
	exec

注意,事务和乐观锁是一起存在的,当你想要用乐观锁的时候,也要使用事务。

四、存在的问题
redis事务没有回滚机制是个硬伤,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值