这边以两个场景举例两种方式
方式 1
通过reids 设锁
/**
*
* @param key
* @param timeoutSec 锁过期时间
* @return
*/
public boolean tryLock(String key, Long timeoutSec) {
//.setIfAbsent(K key, V value):如果键不存在则新增,存在则不改变已经有的值。
//setIfAbsent(K key, V value, Duration timeout) key:key value:值 timeout:过期时间 不存在返回 true 存在 返回false
return redisTemplate.opsForValue().setIfAbsent(key, System.currentTimeMillis() + "", Duration.ofSeconds(timeoutSec));
}
使用代码
场景:如在签到上面使用,通过用户id做标记,同一个用户一直点签到,就可以限制用户并发签到,签到后记得把锁删除,不然就得等到时间过期
public Object userSignIn(String userId) {
String key = "sign_key:"+userId);
if (!redisUtil.tryLock(key, 10L)) {
return "今天已签到,请稍后重试";
}
//删除锁
redisUtil.del(key);
return "签到成功";
}
方式 2
通过mysql 修改时设乐观锁
UPDATE turnplate_count set turnplate_count =16
where user_id = 100065593 and turnplate_count = 17
使用代码
场景:如在转盘上面使用,用户的转盘次数是有限的,在用户一直猛点转盘时,只能有一个操作成功,转盘剩余次数与库内相同转盘次数才能修改成功,有效解决并发,多扣
public Object openTheTurntable(String userId) {
//获取转盘次数
TurnplateCount turnplateCount = turnplateCountMapper.selectOne(new LambdaQueryWrapper<TurnplateCount>()
.eq(TurnplateCount::getUserId, userId));
//扣除转盘次数
Integer count = turnplateCount.getTurnplateCount() - 1;
int res = turnplateCountMapper.updateCount(count, turnplateCount.getTurnplateCount(), userId);
if (res <= 0) {
return "转盘进行中,请稍等";
}
return "得到奖励";
}
/**
* 修改转盘次数
* @param count 更新转盘次数
* @param turnplateCount 原有转盘次数
* @param userId 用户id
*/
@Update("UPDATE turnplate_count SET turnplate_count = #{count} WHERE turnplate_count = #{turnplateCount} AND user_id = #{userId}")
int updateCount(@Param("count") Integer count, @Param("turnplateCount") Integer turnplateCount, @Param("userId") String userId);