业务场景:
提交流程接口,每次调用该接口会将当前流程提交至下一节点。需要避免重复提交流程
解决思路:
1.sychonized 锁
不适用 --- sychonized锁 当代码块被加锁时,后面的请求要等待执行完后才可以执行(排队)。但当短时间内产生同一请求,会重复提交
2.redis缓存
进入方法
---判断缓存中是否有当前流程实例化编号
没有---向REDIS缓存 放入数据
有---拒绝
方法结束时清空缓存
(需要考虑负载均衡,如果有负载均衡要看是不是有集群级别的redis缓存配置)
3.数据库实现加锁
新建加锁表, 保存加锁对象、加锁时间、加锁时长、过期时间
存储过程如下:
/***********************************************
*comment: 取得一个锁,如加锁成功 p_expire_date 不为空,否则 p_expire_date 为空
************************************************/
PROCEDURE LOCK(
target_id IN VARCHAR2, -- 锁 ID
lock_mins IN NUMBER, -- 加锁分钟数
expire_date OUT DATE -- 锁失效时间
) IS
v_lock_date DATE := SYSDATE;
v_type_count number(3);
v_lock_mins NUMBER := p_lock_mins;
v_expire_date DATE;
BEGIN
p_expire_date := NULL;
IF p_lock_mins IS NULL OR p_lock_mins <= 0 THEN
v_lock_mins := 30;
END IF;
v_expire_date := v_lock_date + (lock_mins / 24 / 60 /60);
UPDATE lock l
SET l.lock_date = v_lock_date,
l.expire_date = v_expire_date,
l.updated_by = 'sys',
l.DATE_UPDATED = sysdate
WHERE l.EXPIRE_DATE < SYSDATE
AND l.TARGET_ID = target_id;
IF SQL%FOUND THEN
p_expire_date := v_expire_date;
ELSE
BEGIN
select count(1)
into v_type_count
from wf_lock_mas t
where t.target_id = p_target_id;
if v_type_count = 0 then
INSERT INTO lock
(pk_lock,
target_id,
lock_date,
expire_date,
created_by,
DATE_CREATED,
updated_by,
DATE_UPDATED)
values
(seq_id,
target_id,
v_lock_date,
v_expire_date,
'sys',
sysdate,
'sys',
sysdate);
p_expire_date := v_expire_date;
end if;
if v_type_count > 0 then
p_expire_date := null;
end if;
exception
when dup_val_on_index then
p_expire_date := null;
--RETURN;
END;
END IF;
ENDLOCK;
对应的解锁sql
<!-- 解锁-->
UPDATE SYC_BSE_QL l
SET l.EXPIRE_DATE = sysdate - 0.00001,
l.UPDATED_BY = 'yxd-pms',
l.UPDATED_DATE = SYSDATE
WHERE l.EXPIRE_DATE > SYSDATE
AND l.TARGET_ID = #p_target_id#
AND l.TARGET_TYPE = #p_target_type#