Redis incr 를 사용 하여 병발 문 제 를 해결 하 는 작업

6207 단어 Redisincr 병발
프로젝트 배경:
1.문제 의 작업 명세 서 를 추가 하고 작업 명세서 에 작업 명세서 인 코딩 필드 가 있 으 며 작업 명세서 인 코딩 필드 의 규칙 은'WT'+yyyyMMdd+0000001 이다.
2.매일 작업 명세서 의 생 성 량 이 30W 이기 때문에 병발 문제 가 발생 할 수 있 습 니 다.
해결 방향:
1.우선 redis 가 지연 되 지 않 고 해당 하 는 캐 시 는 삭제 되 지 않 을 것 이 라 고 낙관 합 니 다.(인위적인 조작 을 제외 하고 인위적인 조작 은 독립 적 인 보완 방법 이 있 을 것 입 니 다)
2.작업 목록 인 코딩 을 캐 시 에 저장 합 니 다(redis).그 값 은"WT"+yyyMMdd 뒤의 숫자 부분 만 저장 합 니 다.
대응 하 는 key 는 key 표지+yyyMMdd,즉 매일 하나의 key 입 니 다.
3.작업 목록 인 코딩 을 생 성 할 때마다 redis 의 incr 방법 을 사용 하여 원래 인 코딩 을 바탕 으로 1 을 추가 하고 결 과 를 되 돌려 줍 니 다.
4.돌아 온 결 과 를 판단 합 니 다.돌아 온 것 이 1 이 라면 현재 key 이전에 존재 하지 않 고 생 성 된 새로운 하루 를 위 한 key 를 설명 합 니 다.
이 키 의 수명 주 기 를 24 시간 으로 설정 해 야 합 니 다.
5、키 당 24 시간 만 생존
6.만약 에 redis 가 다운 되 거나 key 가 삭제 되면 지정 한 인 터 페 이 스 를 호출 하고 인 터 페 이 스 는 데이터베이스 에 가서 오늘 의 가장 큰 작업 목록 인 코딩 을 조회 합 니 다.
분석 후 redis 에 존재 하고 뒤의 작업 목록 인 코딩 을 바탕 으로 자체 증가 합 니 다.
7.redisClient 클 라 이언 트 를 자체 적 으로 설정 하고 예화 하 십시오.
코드:
1.인 코딩 핵심 획득 방법

/**
 *                
 * @param redisKey
 * @param codePre
   * @return
   */
 public static String getCodeBySelfRedis(String redisKey,String codePre){
 String nowDateStr = DateTimeUtil.getDateTimeStr(new Date(),DateTimeUtil.DATE_PATTERN_YYYYMMDD);
 Long value = 1L;
 RedisClient uceClient = null;
 Jedis jedis=null;
 try {
  uceClient = SpringContextUtil.getBean("uceClient");
  jedis = uceClient.getResource();
  value = jedis.incr(redisKey+nowDateStr);
  if(value != null){
  //    1        ,    key      24  
  if (value == 1){
   jedis.expire(redisKey+nowDateStr,(24*60*60+1000));
  }
  }else{
  //    ,    
  value = resetCodeRedis(redisKey);
  }
 }catch (Exception e){
  logger.error("               :",e);
  value = resetCodeRedis(redisKey);
 }finally {
  if (uceClient != null){
  uceClient.returnResource(jedis);
  }
 }
 String problemCode = String.valueOf(value);
 for(int i = 0;i < 7;i++){
  if (problemCode.length() < 7){
  problemCode = "0"+problemCode;
  }else{
  break;
  }
 }
 return codePre + nowDateStr + problemCode;
 }
2.지연 시 호출 하 는 핵심 인터페이스 방법

/**
 *       
 * @param redisKey
 * @return
 */
 public static Long resetCodeRedis(String redisKey){
 String oldDateStr = null;
 String nowDateStr = DateTimeUtil.getDateTimeStr(new Date(),DateTimeUtil.DATE_PATTERN_YYYYMMDD);
 //        
 String databaseMaxCode = null;
 //   
 if(StringUtil.isNotEmpty(redisKey) && redisKey.equals(WO_PROBLEM_CODE_KEY)){
  CsWoProblemService csWoProblemService = SpringContextUtil.getBean("csWoProblemService");
  //               
  databaseMaxCode = csWoProblemService.getMaxCode(WO_PROBLEM_CODE_PRE);
  //         
  if(StringUtil.isNotEmpty(databaseMaxCode)){
  oldDateStr = databaseMaxCode.substring(2,10);
  databaseMaxCode = databaseMaxCode.substring(10);
  }
 }else if(StringUtil.isNotEmpty(redisKey) && redisKey.equals(WO_CUST_SER_CODE_KEY)){
  CsWoCustSerService csWoCustSerService = SpringContextUtil.getBean("csWoCustSerService");
  //                   
  databaseMaxCode = csWoCustSerService.getMaxCode("");
  //         
  if(StringUtil.isNotEmpty(databaseMaxCode)){
  oldDateStr = databaseMaxCode.substring(0,8);
  databaseMaxCode = databaseMaxCode.substring(8);
  }
 }
 Long value = getRedisValue(oldDateStr,nowDateStr,databaseMaxCode);
 RedisClient uceClient = null;
 Jedis jedisCluster = null;
 try {
  uceClient = SpringContextUtil.getBean("uceClient");
  jedisCluster = uceClient.getResource();
  boolean keyExist = jedisCluster.exists(redisKey + nowDateStr);
  // NX      set, XX     set, EX  ,PX   
  if (keyExist) {
  jedisCluster.del(redisKey + nowDateStr);
  }
  //     ,    24       
  jedisCluster.set(redisKey + nowDateStr, String.valueOf((value + 1)), "NX","EX", (24*60*60+1000));
 }catch (Exception e){
  logger.error((redisKey + "      :"),e);
 }finally {
  if(uceClient != null){
  uceClient.returnResource(jedisCluster);
  }
 }
 return value + 1;
 }
 
 /**
 *   redis  
 * @param oldDateStr
 * @param nowDateStr
 * @param databaseMaxCode
 * @return
 */
 public static Long getRedisValue(String oldDateStr,String nowDateStr,String databaseMaxCode){
 Long value = 0L;
 String firstCodeZero = "0";
 //      ,           
 if(StringUtil.isNotEmpty(oldDateStr) && StringUtil.isNotEmpty(nowDateStr) && oldDateStr.equals(nowDateStr) && StringUtil.isNotEmpty(databaseMaxCode)){
  for(int i = 0;i < 7;i++){
  String firstCode = databaseMaxCode.substring(0,1);
  if (StringUtil.isNotEmpty(firstCode) && firstCodeZero.equals(firstCode)){
   databaseMaxCode = databaseMaxCode.substring(1);
  }else{
   break;
  }
  }
  if (StringUtil.isNotEmpty(databaseMaxCode)){
  value = Long.parseLong(databaseMaxCode);
  }
 }
 return value;
 }
주의:
jedis 를 사용 한 후에 반드시 close 해 야 합 니 다.그렇지 않 으 면 jedis 연결 이 점점 더 많이 사용 되 고 사용 가능 한 연결 수가 점점 적어 지 며 결국은 redis 가 지연 되 고 최종 프로젝트 가 지연 될 것 입 니 다.
이 항목 은 finally 에서 호출 된 패키지 의 returnResource()방법 입 니 다.이 방법 에서 닫 기 동작 을 합 니 다.
보충 지식:redis 가 높 고 발송 하여 자물쇠 의 실효 문 제 를 야기 합 니 다.

해결 방법:
스 레 드 에 유일한 표 지 를 추가 하여 스 레 드 를 닫 을 때 표지 가 같 는 지 판단 할 수 있 습 니 다.
문제 2:스 레 드 시간 초과 문 제 를 어떻게 해결 하 는 지 같은 시간 에 두 개 또는 두 개 이상 의 스 레 드 가 같은 방법 으로 작 동 합 니 다.
분산 식 잠 금 redisson 사용 하기

이상 레 디 스 incr 를 사용 하여 병발 문 제 를 해결 하 는 작업 은 바로 편집장 이 여러분 에 게 공유 한 모든 내용 입 니 다.여러분 께 참고 가 되 고 저희 도 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기