背景:

业务核心模块只能提交一次,原实现方案 前端加提交限制、后端加数据库业务逻辑判定,结果失效,api站点部署多台负载,切方法需要强求第三方接口 响应时间较慢 ,故放弃lock。

解决方案:redis业务锁。

一、原理

1:利用redis原子性解决并发问题

2:利用redis集群署解决分布式部署问题

3:利用redis性能快解决时间消耗问题

4:利用redis过期时间解决死锁问题

5:利用rediskey唯一性解决互斥问题

问题:超时时间存在误差

二、基础方法

2.1:RedisManager 中重构Set,可以设置When 属性,Always 总是保存,Exists 存在时保存,NotExists 不存在时保存。返回值中true与false代表是否操作。

设置notExists模式可以判定redis中是否存在值

 public static bool Set<T>(string key, T objectValue, long lNumofSeconds = , StackExchange.Redis.When when =When.Always)
{
if (!Enum.IsDefined(typeof(When), when))
throw new InvalidEnumArgumentException(nameof(when), (int) when, typeof(When));
bool result = false;
try
{
key = redisConfigInfo.KeySuffix + key;
if (lNumofSeconds > 0L)
{
return ManagerMaster.GetDatabase(-, null).StringSet(key, ConvertJson<T>(objectValue), new TimeSpan?(TimeSpan.FromSeconds((double)lNumofSeconds)), when, CommandFlags.None);
}
return ManagerMaster.GetDatabase(-, null).StringSet(key, ConvertJson<T>(objectValue), null, when, CommandFlags.None);
}
catch (Exception) { result = false; }
return result;
}
namespace StackExchange.Redis
{
public enum When
{
Always,
Exists,
NotExists,
}
}

2.2:判定是否存在redis缓存 ,如果存在则返回true 如果不存在就返回false并保存值

 /// <summary>
/// 判定缓存是否存在
/// 不存在就添加缓存
/// </summary>
/// <param name="redisKey"></param>
/// <param name="inputValue">redis值</param>
/// <param name="timeSecond">过期时间/秒</param>
/// <param name="cacheType">{0:cache;2=redis};默认redis</param>
/// <returns>true 代表存在redis false 代表不存在redis 自动写入</returns>
public static bool CheckRedisNoExistSet(string redisKey, string inputValue, int timeSecond = ,int cacheType=)
{
//redis写 NX-- Only set the key if it does not already exist.
//true写成功 无数据 写入,false 没写 或者异常
return !RedisManager.Set(redisKey, inputValue, timeSecond, When.NotExists);
}

三、应用

通过redis 来实现业务锁功能

1:最小单位可是精确到某一个表的ID ,例如:reportID

2:如果正在处理这个案件则阻止其他并发操作

3:自动过期时间为120秒,方法执行完毕自动释放

/// <summary>
/// 正式全部提交
/// 1.返回code=0表示存在重复案件
/// 2.首次IsContinue传0,继续提交IsContinue传1
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost, Log("全部提交")]
public BaseResponse CenterSubmitAllSimpleCase([FromBody]CenterSubmitAllSimpleCaseRequest request)
{
var redisKey = string.Format(ConfigurationManager.AppSettings["CenterSubmitAllSimpleCase"], request.ReportId.ToString());
if (CacheProvider.CheckRedisNoExistSet(redisKey, request.ReportId.ToString()))
{
return BaseResponse.GetBaseResponse(BusinessStatusType.Failed, "请勿重复提交");
}
var centerFlow = _centerFlowService.QueryCenterFlowByReportId(request.ReportId).Any(e => e.Status == (int)SubmitCenterStatus.提交中);
if (centerFlow)
return BaseResponse.GetBaseResponse(BusinessStatusType.Failed, "请勿重复提交");
request.CenterSubmitType = CenterSubmitType.全部提交;
BaseResponse result = _callBackService.SubmitCompleteToCenter(request);
CacheProvider.Remove(redisKey);
return result;
}
<!--全部提交业务锁-->
<add key="CenterSubmitAllSimpleCase" value="fc_centerSubmitAllSimpleCase_{0}_feiCheRedis20"/>

redis 业务锁 not exist 模式的更多相关文章

  1. springBoot实现redis分布式锁

    参考:https://blog.csdn.net/weixin_44634197/article/details/108308395 .. 使用redis的set命令带NX(not exist)参数实 ...

  2. Redis 分布式锁|从青铜到钻石的五种演进方案

    缓存系列文章: 缓存实战(一):20 图 |6 千字|缓存实战(上篇) 缓存实战(二):Redis 分布式锁|从青铜到钻石的五种演进方案 缓存实战(三):分布式锁中的王者方案 - Redisson 上 ...

  3. Redis分布式锁 (图解-秒懂-史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  4. spring boot redis分布式锁

    随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁.分布式锁的实现有很多种,比如基于数据库. zookeeper 等,本文主要介绍使用 Redis 做分布式锁的方式,并封装成spring b ...

  5. 4、redis 分布式锁

    1. 前言 关于分布式锁的实现,目前常用的方案有以下三类: 数据库乐观锁: 基于分布式缓存实现的锁服务,典型代表有 Redis 和基于 Redis 的 RedLock: 基于分布式一致性算法实现的锁服 ...

  6. Redlock(redis分布式锁)原理分析

    Redlock:全名叫做 Redis Distributed Lock;即使用redis实现的分布式锁: 使用场景:多个服务间保证同一时刻同一时间段内同一用户只能有一个请求(防止关键业务出现并发攻击) ...

  7. Redis分布式锁的实现

    前段时间,我在的项目组准备做一个类似美团外卖的拼手气红包[第X个领取的人红包最大],基本功能实现后,就要考虑这一操作在短时间内多个用户争抢同一资源的并发问题了,类似于很多应用如淘宝.京东的秒杀活动场景 ...

  8. redis分布式锁redisson

    原文:https://blog.csdn.net/Kincym/article/details/78697472 关于redisson的源代码请参考官网:https://github.com/redi ...

  9. Redisson实现Redis分布式锁的N种姿势(转)

    Redis几种架构 Redis发展到现在,几种常见的部署架构有: 单机模式: 主从模式: 哨兵模式: 集群模式: 我们首先基于这些架构讲解Redisson普通分布式锁实现,需要注意的是,只有充分了解普 ...

随机推荐

  1. js 的七大原则--单一原则、开闭原则、替换原则(一)

    一.前言: js 的七大设计原则: 1.单一原则 2.开闭原则 3.里氏替换原则 4.依赖倒转原则 5.接口隔离原则 6.合成复用原则 7.迪米尔法则 二.单一原则 1.定义:单一原则就是一个对象或者 ...

  2. SYBASE扩充日志段空间

    有时候日志段空间满了使用下列语句也无济于事,又不能直接重启库,就加空间应急,dump tran QAS with truncate_only dump tran QAS with no_log sp_ ...

  3. a标签中target属性为“_blank”时存在安全问题

    今天看到一个比较有意思的洞,虽然不够严重,但是却普遍存在各大src中 熟悉js的朋友都应该知道当我们在调用window下的open方法创建一个新窗口的同时,我们可以获得一个创建窗口的opener句柄, ...

  4. org.w3c.dom document 和xml 字符串 互转

    转自:https://blog.csdn.net/wmyasw/article/details/8686420 package com.mymhotel.opera; import java.io.F ...

  5. C# 利用特性(Attribute)实现通用实体类数据合法校验

    用过asp.net mvc 的都应该知道,在实体类上添加一些特性,可以实现后端实体的数据校验,这里简单实现一下 实现原理:利用反射获取实体的每一个属性,并通过属性获取属性上标注的特性,调用特性的Val ...

  6. unity 3D物体使用EventSystem响应事件

    在ugui中创建一个canvas 之后会自动创建一个EventSystem,用来处理UI上的时间响应.(可以通过UI>EventSystem创建EventSystem) EventSystem ...

  7. python(函数调用)

    1.在原文件中调用 def abc(x,y): print x + y abc(2,3) #直接通过函数名加括号进行调用传参 2.同一个包(package)下面调用不同文件中的函数 "&qu ...

  8. Oracle 限制行的子句

    12c新特性 限制行的子句允许限制查询返回的行.可以指定偏移量,以及要返回的行数或百分比.您可以使用此子句实现Top-N报告.要获得一致的结果,请指定ORDER_by子句以确保具有确定性的排序顺序. ...

  9. angularcli 第二篇(数据绑定、属性申明、绑定属性)

    1.数据绑定 插值绑定: <li>{{ hero.name }} </li>       或       <div  class = "{{ demo }}&q ...

  10. gitlab及jenkins

    1.安装配置gitlab服务,在gitlab新建一个仓库,配置本地密钥,并通过ssh方式拉取gitlab仓库代码 https://packages.gitlab.com/gitlab/gitlab-c ...