Development Tip - Lock

  • 공부나 경험을 통해 얻은, 개발에서 활용할 내용들을 담은 포스팅

1. Redis Watch Multi 활용 해야하는 경우 ( 동시성 - 낙관적 LOCK )

  • 예를들어 배달의 민족에서 주문을 하면, 라이더들이 서로 자기가 배달을 하기 위해 해당 주문을 잡는다.
  • 이 때 동시에 하나의 주문을 잡을 때 동시성이 일어나서 중복으로 라이더가 주문을 잡는 일을 방지해야 한다.
  • 그럴 때 Redis에서 낙관적 LOCK을 해당 key에만 걸어서
  • 단 한 명의 라이더만 주문을 잡을 수 있게 처리 해야한다.



2. Redis 분산 LOCK 활용하기 ( Red-Lock )

  • 레디스에는 pub sub 이라는 것이있다.
    • 메시지를 받으면 subscriber 에게 메시지 전달 가능한다
      • 단, Message Queue 와는 다름. Message Queue 의 경우 메시지를 받았다는 ack 가 와야 메시지 큐에서 비워지는데 Redis 는 그냥 전달한다.
  • 이걸 분산 LOCK으로 적용할 수 있는데, 해당 Key 값에 LOCK을 걸었다가 완료되면 해제하고를 반복한다.
  • 그러면 예를들어 포인트를 사용가능한 돈으로 전환을 할 때, 악의 적인 프로그램으로 연달아 눌러서 스레드를 보내는 기능을 사용했다고 가정하면 그러한 경우 보유한 포인트보다 많은 양의 포인트가 전환되는 오류를 막을 수 있다.



3. 보상 트랜잭션 활용하기

  • 예를 들어 쿠폰 발급을 100명으로 지정해놨을 때 동시성 때문에 100명 넘게 발급이 되면 안된다.
  • 그럴 때 사용하는게 보상 트랜잭션이다.
  • 일단 100명 넘게 발급을 하고, 넘어가는 사람들에게는 예외 문구를 보내준 뒤, Redis나 DB에서 다시 마이너스를 해주는 방식이다.
      @Test
      public void test() throws InterruptedException {
          final ValueOperations valueOperations = redisTemplate.opsForValue();
    
          blitzer.blitz(() -> {
    
              final String count5 = "count8";
              final Object count1 = valueOperations.get(count5);
    
              // limit
              final int i = 30000;
    
    
              if (count1 != null && Long.parseLong(count1.toString()) > i) {
                  return;
              }
    
              final Long count2 = valueOperations.increment(count5);
    					
              if (count2 > i) {
                  valueOperations.decrement(count5);
                  //그리고 추가적으로 사용자한테 예외를 던져주는 로직이 필요함
                  //요청한 것이 해당 제한 범위를 넘어섯다
              }
          });
      }
    
    • 멀티스레드 환경을 java에서 테스트 하고 싶다면, Jmock의 Blitzer를 활용할 수 있다.






results matching ""

    No results matching ""