一、基于数据库的悲观锁
对数据的读取采取比较悲观的态度,在A用户读取数据的时候认为B也会来读取数据修改,所以在A读取数据的时候开启事务锁定数据,只要A不提交事务,B就无法读取数据。通常使用for update 来实现。一般用在读少写多的情况。
例:
select t.clom from sys.temp t where t.id=1 for update;
二、基于数据库的乐观锁
对数据的读取采取比较乐观的态度的态度,认为在A用户读取数据的时候不会有其他用户来读取数据修改。通常在查询数据的时候查询出时间戳或者版本号,在更新数据时使用时间戳或版本号来保证数据的一致性。适用于读多写少的情况。
例:
update sys.temp t set t.update_time=sysdate ,t.clom='测试数据' where t.id=#{id,jdbcType=INTEGER} and t.upadte_time=#{updateTime,jdbcType=TIMESTAMP};
三、基于redis方式实现
在redis中有一个方法setnx,即set if not exists,只有当键不存在的时候才可以设置成功,我们可以利用它来实现锁的效果。
在springBoot项目中,我们利用redisTemplate组件来实现
//值
final String value = System.nanoTime()+""+ UUID.randomUUID();
boolean result = false;
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
try {
result = ops.setIfAbsent("redis-key-lock", value, 60L, TimeUnit.SECONDS);
if (result) {
//执行业务操作
}
} catch (Exception e) {
throw e;
}finally {
//加锁成功并访问操作完共享资源后释放锁
if (value.equals(ops.get("redis-key-lock"))) {
redisTemplate.delete("redis-key-lock");
}
}