redis 業務鎖 not exist 模式

背景:

業務核心模塊只能提交一次,原實現方案 前端加提交限制、後端加數據庫業務邏輯斷定,結果失效,api站點部署多臺負載,切方法須要強求第三方接口 響應時間較慢 ,故放棄lock。前端

解決方案:redis業務鎖。redis

1、原理

1:利用redis原子性解決併發問題數據庫

2:利用redis集羣署解決分佈式部署問題後端

3:利用redis性能快解決時間消耗問題api

4:利用redis過時時間解決死鎖問題緩存

5:利用rediskey惟一性解決互斥問題併發

 

問題:超時時間存在偏差分佈式

2、基礎方法

2.1RedisManager 中重構Set,能夠設置When 屬性,Always 老是保存,Exists 存在時保存,NotExists 不存在時保存。返回值中truefalse表明是否操做。ide

設置notExists模式能夠斷定redis中是否存在值 性能

 

 1 public static bool Set<T>(string key, T objectValue, long lNumofSeconds = 0, StackExchange.Redis.When when =When.Always)
 2         {
 3             if (!Enum.IsDefined(typeof(When), when))
 4                 throw new InvalidEnumArgumentException(nameof(when), (int) when, typeof(When));
 5             bool result = false;
 6             try
 7             {
 8                 key = redisConfigInfo.KeySuffix + key;
 9                 if (lNumofSeconds > 0L)
10                 {
11                     return ManagerMaster.GetDatabase(-1, null).StringSet(key, ConvertJson<T>(objectValue), new TimeSpan?(TimeSpan.FromSeconds((double)lNumofSeconds)), when, CommandFlags.None);
12                 }
13                 return ManagerMaster.GetDatabase(-1, null).StringSet(key, ConvertJson<T>(objectValue), null, when, CommandFlags.None);
14             }
15             catch (Exception) { result = false; }
16             return result;
17         }

 

namespace StackExchange.Redis
{
  public enum When
  {
    Always,
    Exists,
    NotExists,
  }
}

 

 

2.2:斷定是否存在redis緩存 ,若是存在則返回true 若是不存在就返回false並保存值

 1 /// <summary>
 2         /// 斷定緩存是否存在
 3         /// 不存在就添加緩存
 4         /// </summary>
 5         /// <param name="redisKey"></param>
 6         /// <param name="inputValue">redis值</param>
 7         /// <param name="timeSecond">過時時間/秒</param>
 8         /// <param name="cacheType">{0:cache;2=redis};默認redis</param>
 9         /// <returns>true 表明存在redis false 表明不存在redis 自動寫入</returns>
10         public static bool CheckRedisNoExistSet(string redisKey, string inputValue, int timeSecond = 120,int cacheType=1)
11         {
12             //redis寫 NX-- Only set the key if it does not already exist.
13             //true寫成功 無數據 寫入,false 沒寫 或者異常  
14             return !RedisManager.Set(redisKey, inputValue, timeSecond, When.NotExists);
15         }

 

 

3、應用

經過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"/>
相關文章
相關標籤/搜索