博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redission中分布式锁的简单应用
阅读量:3930 次
发布时间:2019-05-23

本文共 4180 字,大约阅读时间需要 13 分钟。

之前笔者使用Redission中tryLock方法时碰到了一些问题,本来加锁之后不应该出现多次访问DB的情况,可事实上在打印出的日志中显示有多次访问数据库,因而笔者查了一些资料了解了下trylock的基本实现原理,在这里记录一下,如有不当之处,还请各位看官不吝指证

目录


一、Redission中tryLock的基本实现原理

Redission中的tryLock是基于分布式锁来实现的,其内部是使用redis中原生setnx再补齐续命逻辑达到最终效果的。通俗来讲就是一个服务部署在了多个服务器上,然后共享一把锁,当这把锁没有释放时其他线程会进行等待,直至当前持有锁的线程执行完成将锁释放,如果锁超时了但是当前持有线程还未执行完成,则会触发续命机制重置当前锁的超时时间,直至当前持有锁的线程执行完成后自行释放锁。

二、Redission中tryLock的简单使用

1、需要的依赖

org.springframework.boot
spring-boot-starter-data-redis
org.redisson
redisson
3.15.6

2、基本实现

package com.muyichen.demo.service.impl;import com.baomidou.mybatisplus.core.toolkit.Wrappers;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.muyichen.demo.dao.UserMapper;import com.muyichen.demo.entity.User;import com.muyichen.demo.service.IUserService;import com.muyichen.demo.service.RedissonCommonService;import com.muyichen.demo.util.RedisOpsUtil;import lombok.extern.slf4j.Slf4j;import org.redisson.api.RBucket;import org.redisson.api.RLock;import org.redisson.api.RedissonClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;/** * 

* 用户表 服务实现类 *

* * @author muyichen * @since 2021-06-17 */@Slf4j@Servicepublic class UserServiceImpl extends ServiceImpl
implements IUserService {
@Autowired private UserMapper userMapper; @Autowired private RedissonClient redissonClient; @Autowired private RedisOpsUtil
redisOpsUtil; @Override public User getUserById(Long id) {
return getUseTryLock(id); } /** * 使用tryLock上锁 * @param id * @return */ private User getUseTryLock(Long id) {
//先从缓存中查询是否存在用户信息 User resultUser = redisOpsUtil.get("User:" + id, User.class); if (null != resultUser) {
return resultUser; } // 获取当前查询所对应的锁 RLock lock = redissonClient.getLock("Lock:" + id); try {
//判断是否能拿到锁 if(lock.tryLock(0, 5, TimeUnit.SECONDS)) {
//如果能拿到锁,则去数据库中查询数据 resultUser = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getId, id).last("limit 1")); log.info("走数据库:{}", id); //并将查询出的数据放入缓存中 redisOpsUtil.set("User:" + id, resultUser, 360L, TimeUnit.SECONDS); } else {
Thread.sleep(50); //如果拿不到锁则回调当前方法 getUserById(id); } } catch (Exception e) {
e.printStackTrace(); } finally {
if(lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock(); } } return resultUser; } /** * 使用lock上锁(双重检测) * @param id * @return */ private User getUseLock(Long id) {
//先从缓存中查询是否存在用户信息 User resultUser = redisOpsUtil.get("User:" + id, User.class); if (null != resultUser) {
return resultUser; } // 获取当前查询所对应的锁 RLock lock = redissonClient.getLock("Lock:" + id); try {
lock.lock(); resultUser = redisOpsUtil.get("User:" + id, User.class); if (null != resultUser) {
return resultUser; } //如果缓存中没有则去数据库中查询数据 resultUser = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getId, id).last("limit 1")); log.info("走数据库:{}", id); //并将查询出的数据放入缓存中 redisOpsUtil.set("User:" + id, resultUser, 360L, TimeUnit.SECONDS); } catch (Exception e) {
e.printStackTrace(); } finally {
if(lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock(); } } return resultUser; }}

三、tryLock中的三个参数

在这里插入图片描述

wait:表示等待时间,就是之后的线程会等待当前现场释放锁的时间

leaseTime:表示锁超时时间
unit:表示前面两个时间的单位

四、使用过程中遇到的问题

1、WRONGTYPE Operation against a key holding the wrong kind of value

在这里插入图片描述

出现这个问题,是因为笔者之前将lock的key和User的key设置成一样的了,但是两者的类型是不一样的。所以设置key的时候要注意唯一性

2、并发量的局限

单台服务器的情况下,如果一开始没有缓存,那么一旦超过800的并发数量,那么就会出现Error

转载地址:http://kktgn.baihongyu.com/

你可能感兴趣的文章
[敏捷开发培训] 什么是敏捷开发中的Spike?
查看>>
[敏捷开发培训] 精益软件开发中的8中浪费(Lean Software Development)
查看>>
[敏捷开发实践] 高质量软件交付之概念模型
查看>>
研发主管的烦恼:如何考核Project Manager
查看>>
杂谈数字化转型(Data Transformation,DX)
查看>>
JAVA算法:无向图的表示
查看>>
[数据分析学习笔记] 数据分析处理流程
查看>>
[数据分析学习笔记] 数据挖掘建模过程
查看>>
[数据分析学习笔记] 数据分析必备的概率论和统计学知识
查看>>
[数据分析学习笔记] 异常值分析方法
查看>>
[统计学笔记] 统计学学习笔记重点总结
查看>>
[统计学笔记] (一) 统计学的基本概念
查看>>
[统计学笔记](二)收集数据
查看>>
[统计学笔记三] 整理和显示数据
查看>>
[统计学笔记九] 方差分析(ANOVA)
查看>>
[机器学习笔记] (一)机器学习基本概念篇(含思维导图)
查看>>
[机器学习笔记] 混淆矩阵(Confusion Matrix)
查看>>
[机器学习笔记] Python 绘制ROC曲线的例子
查看>>
[机器学习笔记] 机器学习中的“过拟合(Overfitting)”和“欠拟合(Underfitting)”
查看>>
[机器学习笔记] 特征(Feature)和特征选择(Feature Selection)
查看>>