乐观锁描述:

大多数是基于数据版本(version)的记录机制实现的。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个”version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。

  • 悲观锁:锁数据记录,不给操作
  • 乐观锁机制:CAS,compare and set ,swap(交换)

        数据库操作例子:
                update t_user set name? ,version=old_version +1 where id=? and version=old_version

ABA问题
采用业务字段会导致ABA问题
即:A开始取的时候store=100,B开始取的时候也是store=100,然后B对数据做了一系列的操作后,B又将store改回了store=100。
当A提交数据的时候,检查store是否等于100时,检查通过,于是将数据更新。导致了ABA问题出现。
最终采用version方式,自动递增,避免ABA问题的出现。即不采用业务字段控制版本号,防止修改。

redis aba redis aba问题_乐观锁

 

redis实现乐观锁实现机制

Redis中使用watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了exec,discard,unwatch命令都会清除连接中的所有监视。

Redis的事务是下面4个命令来实现 

  1. multi,开启Redis的事务,置客户端为事务态。 
  2. exec,提交事务,执行从multi到此命令前的命令队列,置客户端为非事务态。 
  3. discard,取消事务,置客户端为非事务态。 
  4. watch,监视键值对,作用时如果事务提交exec时发现监视的监视对发生变化,事务将被取消。 

 

个人理解:

redis的乐观锁实现,就是通过watch命令实现乐观锁的,在开启事务之前先watch键key的版本号,在exec命令执行时,检查被监视的键key是否被修改了,如果被修改了服务器将拒绝执行事物,并向客户端返回 nil 空。

redis aba redis aba问题_乐观锁_02