当前位置: 首页 > wzjs >正文

天津建设网站天津市地铁规划图网站建设行业分析报告

天津建设网站天津市地铁规划图,网站建设行业分析报告,群晖wordpress配置文件,做的王者荣耀钓鱼网站项目利用 Redis 实现分布式锁,提供两种使用方式: 编程式锁(通过 Redisson 显式加锁/解锁)和 声明式锁(通过 Lock4j 注解自动管理锁) 以下以支付通知模块(PayNotify)为例&#xff…

项目利用 Redis 实现分布式锁,提供两种使用方式:

编程式锁(通过 Redisson 显式加锁/解锁)和

声明式锁(通过 @Lock4j 注解自动管理锁)

以下以支付通知模块(PayNotify)为例,详细解析两种方式的实现过程。

1. 编程式锁(基于 Redisson)

编程式锁通过 Redisson 框架提供灵活的分布式锁操作,适合需要精细控制锁逻辑的场景。 PayNotify 模块使用编程式锁确保支付通知任务的并发安全。

实现步骤
步骤 1:引入 Redisson 依赖

在模块的 pom.xml 中添加 Redisson 依赖:

<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.25.1</version> <!-- 建议使用最新版本 -->
</dependency>
  • 解释
    • redisson-spring-boot-starter 提供 Redisson 客户端,支持多种分布式锁类型(如普通锁、红锁、读写锁)。
    • 已在 Redis 缓存模块配置好 Redisson 和 Spring Data Redis,无需额外配置。
步骤 2:定义 Redis 锁键

在 RedisKeyConstants 接口中,定义支付通知任务的分布式锁键:

/*** System Redis Key 枚举类*/
public interface RedisKeyConstants {/*** 指定部门的所有子部门编号数组的缓存* <p>* KEY 格式:dept_children_ids:{id}* VALUE 数据类型:String 子部门编号集合*/String DEPT_CHILDREN_ID_LIST = "dept_children_ids";/*** 角色的缓存* <p>* KEY 格式:role:{id}* VALUE 数据类型:String 角色信息*/String ROLE = "role";/*** 用户拥有的角色编号的缓存* <p>* KEY 格式:user_role_ids:{userId}* VALUE 数据类型:String 角色编号集合*/String USER_ROLE_ID_LIST = "user_role_ids";/*** 拥有指定菜单的角色编号的缓存* <p>* KEY 格式:menu_role_ids:{menuId}* VALUE 数据类型:String 角色编号集合*/String MENU_ROLE_ID_LIST = "menu_role_ids";/*** 拥有权限对应的菜单编号数组的缓存* <p>* KEY 格式:permission_menu_ids:{permission}* VALUE 数据类型:String 菜单编号数组*/String PERMISSION_MENU_ID_LIST = "permission_menu_ids";/*** OAuth2 客户端的缓存* <p>* KEY 格式:oauth_client:{id}* VALUE 数据类型:String 客户端信息*/String OAUTH_CLIENT = "oauth_client";/*** 访问令牌的缓存* <p>* KEY 格式:oauth2_access_token:{token}* VALUE 数据类型:String 访问令牌信息 {@link OAuth2AccessTokenDO}* <p>* 由于动态过期时间,使用 RedisTemplate 操作*/String OAUTH2_ACCESS_TOKEN = "oauth2_access_token:%s";/*** 站内信模版的缓存* <p>* KEY 格式:notify_template:{code}* VALUE 数据格式:String 模版信息*/String NOTIFY_TEMPLATE = "notify_template";/*** 邮件账号的缓存* <p>* KEY 格式:mail_account:{id}* VALUE 数据格式:String 账号信息*/String MAIL_ACCOUNT = "mail_account";/*** 邮件模版的缓存* <p>* KEY 格式:mail_template:{code}* VALUE 数据格式:String 模版信息*/String MAIL_TEMPLATE = "mail_template";/*** 短信模版的缓存* <p>* KEY 格式:sms_template:{id}* VALUE 数据格式:String 模版信息*/String SMS_TEMPLATE = "sms_template";/*** 小程序订阅模版的缓存** KEY 格式:wxa_subscribe_template:{userType}* VALUE 数据格式 String, 模版信息*/String WXA_SUBSCRIBE_TEMPLATE = "wxa_subscribe_template";}
  • 解释
    • 键格式为 pay_notify:lock:{id},如 pay_notify:lock:123,确保每个任务有唯一锁。
    • 使用模板字符串,便于动态生成。
步骤 3:实现锁操作类

创建 PayNotifyLockRedisDAO 类,使用 Redisson 实现加锁和解锁:

@Repository
public class PayNotifyLockRedisDAO {@Resourceprivate RedissonClient redissonClient;public void lock(long id, long timeoutMillis, Runnable action) {String lockKey = formatKey(id);RLock lock = redissonClient.getLock(lockKey);try {// 加锁lock.lock(timeoutMillis, TimeUnit.MILLISECONDS);// 执行逻辑action.run();} finally {// 解锁lock.unlock();}}private static String formatKey(Long id) {return String.format(RedisKeyConstants.PAY_NOTIFY_LOCK, id);}
}

解释

  • 依赖注入:RedissonClient 由 Redisson Starter 提供。
  • 方法 lock
    1. 生成键:根据任务 ID 格式化锁键。
    2. 获取锁:通过 redissonClient.getLock(key) 获取锁对象,lock.lock(timeoutMillis, TimeUnit.MILLISECONDS) 设置加锁超时。
    3. 执行逻辑:在 try 块中执行传入的 Runnable 逻辑。
    4. 释放锁:在 finally 块中调用 lock.unlock(),确保锁释放。
  • 安全性:try-finally 结构保证锁一定释放,防止死锁。
步骤 4:应用锁

在 PayNotifyServiceImpl 中使用 PayNotifyLockRedisDAO 加锁:

@Service
public class PayNotifyServiceImpl implements PayNotifyService {public static final long NOTIFY_TIMEOUT_MILLIS = 120 * 1000; // 120秒@Resourceprivate PayNotifyLockRedisDAO payNotifyLockRedisDAO;@Resourceprivate PayNotifyTaskMapper payNotifyTaskMapper;@Overridepublic void executeNotifySync(PayNotifyTaskDO task) {payNotifyLockRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> {// 校验任务是否已过期PayNotifyTaskDO dbTask = payNotifyTaskMapper.selectById(task.getId());if (DateUtils.afterNow(dbTask.getNextNotifyTime())) {log.info("[executeNotify][任务({}) 忽略,未到通知时间]", dbTask.getId());return;}// 执行通知逻辑executeNotify(dbTask);});}private void executeNotify(PayNotifyTaskDO task) {// 模拟通知逻辑log.info("[executeNotify][执行任务 {}]", task.getId());}
}
  • 解释
    • 注入:注入 PayNotifyLockRedisDAO 用于锁操作。
    • 加锁:调用 lock 方法,传入任务 ID、超时时间(120秒)和业务逻辑(Runnable)。
    • 校验:加锁后再次查询任务状态,防止并发重复执行。
    • 执行:调用 executeNotify 完成通知。
    • 优势:编程式锁显式控制锁的范围和释放时机,适合复杂逻辑。
步骤 5:为什么选择 Redisson?
  • 多类型锁:支持普通锁、红锁、读写锁等,满足不同场景。
  • 高可靠性:内置看门狗机制,自动延长锁超时时间。
  • 易用性:API 直观,集成 Spring 简单。

2. 声明式锁(基于 Lock4j)

声明式锁通过 Lock4j 的 @Lock4j 注解提供简洁的分布式锁支持,适合快速开发。Yudao 默认未启用 Lock4j,需手动引入。

实现步骤
步骤 1:引入 Lock4j 依赖

在 pom.xml 中添加 Lock4j 依赖:

<dependency><groupId>com.baomidou</groupId><artifactId>lock4j-redisson-spring-boot-starter</artifactId><version>2.2.4</version>
</dependency>
  • 解释
    • lock4j-redisson-spring-boot-starter 整合 Lock4j 和 Redisson,提供 Redis 分布式锁。
    • 默认 optional=true,需移除以启用。
步骤 2:配置 Lock4j

在 application-local.yml 中配置 Lock4j 参数:

lock4j:
  acquire-timeout: 3000 # 获取锁超时时间(毫秒)
  expire: 30000 # 锁过期时间(毫秒)

  • 解释
    • acquire-timeout:尝试获取锁的最长时间,超时后抛出异常。
    • expire:锁的自动过期时间,防止死锁。
    • 默认值适合大多数场景,可根据业务调整。
步骤 3:应用 @Lock4j 注解

在服务方法上添加 @Lock4j 注解:

@Service
public class DemoService {@Lock4jpublic void simple() {// 模拟业务逻辑log.info("[simple][执行简单逻辑]");}@Lock4j(keys = {"#user.id", "#user.name"}, expire = 60000, acquireTimeout = 1000)public User customMethod(User user) {log.info("[customMethod][处理用户 {}]", user);return user;}
}@Data
class User {private Long id;private String name;
}
  • 解释
    • 简单锁:simple 方法使用默认配置,锁键基于方法签名。
    • 自定义锁:customMethod 使用 SpEL 表达式(#user.id, #user.name)生成锁键,设置 60秒过期和 1秒获取超时。
    • 机制:Lock4j 自动在方法执行前加锁,执行后解锁,基于 Redis 实现。
步骤 4:Lock4j 的优势
  • 简洁:注解式开发,减少样板代码。
  • 灵活:支持 SpEL 表达式自定义锁键。
  • 多后端:支持 Redis、ZooKeeper 等,Redisson 仅为一种实现。


文章转载自:

http://ZkPasmKj.gsyns.cn
http://T6woHpGj.gsyns.cn
http://m6wth2Zm.gsyns.cn
http://4wETV1Bu.gsyns.cn
http://FfhPT1da.gsyns.cn
http://XErK1Nwu.gsyns.cn
http://x6GBP90D.gsyns.cn
http://nSsT0bh2.gsyns.cn
http://433WxAaY.gsyns.cn
http://lqOlk5vV.gsyns.cn
http://GiRdbEvn.gsyns.cn
http://Yup4X5n9.gsyns.cn
http://MKH2S4Ih.gsyns.cn
http://xHD33hUK.gsyns.cn
http://ja9ZMi1e.gsyns.cn
http://w3vl30vp.gsyns.cn
http://ryqZjW2O.gsyns.cn
http://JwHMbSAt.gsyns.cn
http://qREYrt9Z.gsyns.cn
http://8b0wHPQY.gsyns.cn
http://n5FPdjza.gsyns.cn
http://MRQJAJPb.gsyns.cn
http://25qn42yY.gsyns.cn
http://vFCfWeYe.gsyns.cn
http://EwBC9hvU.gsyns.cn
http://Pd83sHCY.gsyns.cn
http://87VRUYHN.gsyns.cn
http://RkggGhS7.gsyns.cn
http://cAlMdET1.gsyns.cn
http://2F8De3aa.gsyns.cn
http://www.dtcms.com/wzjs/719554.html

相关文章:

  • 深圳网站设计招聘信息u nas 建设网站
  • 知科网站乾安网站建设
  • 内部网站建设公司c 可以做网站吗
  • 网站建设通知广州越秀区核酸检测点查询
  • 杭州萧山区专门做网站的公司企业建设网站的功能是什么意思
  • 云南网站建设首选公司网站开发原始数据
  • 做全屏式网站尺寸是多大网站做专题主题该怎么选
  • 网站内容规划要包括什么内容wordpress 数据库优化
  • jsp 哪些网站品牌高端网站制作企业
  • 凤岗镇网站建设网络推广公司成都
  • 门户网站开发分类东莞路桥投资建设公司招聘
  • 网站建设驻地开发合同阿里巴巴网站域名
  • 成都做网站的工资多少想要导航页面推广app
  • 论坛网站太难做没人微网站免
  • 做黑彩网站图片把网站放到服务器上
  • 自助建站系统加盟网站广告文案
  • 网站建设方案对比分析外卖网站建设方案书
  • 网站留言模块html的基本结构
  • 做网站去哪里好为什么要推行政务公开网站建设
  • 成都建设网站 scgckj中国学校网站前台模板
  • 高校信息化建设网站系统微信在网站文字上做超链接
  • 科大讯飞哪些做教学资源的网站卡片式网站模板
  • 网站怎么做来流量宝安高端网站建设
  • 移动建站工具西安城乡住房建设厅网站首页
  • 南通建设中标查询网站网站返回指定位置怎么做
  • 欣赏艺术类的网站手机网站建设怎么设计
  • 网站不备案的后果课程中心网站建设内容
  • 网站商城app 建设方案wordpress流量统计放在哪里
  • 网站建设创业公司策划方案建设美食电子商务网站
  • 企业免费网站建设模板下载河北建设部网站