Redis 대기열에 정기적으로 다중 프로세스 중복없이 값 추가

4033 단어 Redis루비
resque의 큐에 정기적으로 타임 스탬프를 추가해, cron 적으로 사용하고 싶었지만, 큐에 추가하는 처리를 1 개의 프로세스로 하는 것은 가용성이 낮기 때문에, (복수의 서버에 분산했다) 복수 프로세스에서 중복없이 값을 추가하고 싶었습니다.

아래의 방법으로 잘 될 것 같다.
  • 마지막에 값을 추가했을 때의 타임 스탬프를 보관 유지 해, 추가 전에 체크한다
  • Redis의 트랜잭션 메커니즘을 사용하여 1이지만 거의 동시에 실행될 때 중복 될 수 있으므로

  • 다음은 초당 타임 스탬프를 대기열에 추가하는 예입니다.
    # cron.rb
    require "redis"
    require "json"
    
    QUEUE_NAME = "per_sec" # キューの名前
    TIMESTAMP_NAME = "per_sec_timestamp" # 最後にキューに値を追加したときのタイムスタンプ
    
    redis = Redis.new
    
    loop do
      t = Time.now.to_i
    
      redis.watch(TIMESTAMP_NAME) # TIMESTAMP_NAME の値が exec までに変わっていれば multi - exec 間のコマンドを失敗させる
      last = redis.get(TIMESTAMP_NAME).to_i
    
      if last < t
        redis.multi
        redis.rpush(QUEUE_NAME, t)
        redis.set(TIMESTAMP_NAME, t)
        redis.exec ? puts("set #{t}") : puts("transaction fail")
      end
      sleep 0.1
    end
    

    위의 스크립트를 2 프로세스 시작하고 while true; do redis-cli lpop per_sec; sleep 0.1s; done 에서 큐의 내용을 pop 계속 하면 다음과 같이 되어 중복 없이 큐에 추가할 수 있는 것을 알 수 있다.



    Redis가 클러스터 모드에 대응



    클러스터 모드의 경우 MULTI - EXEC 간의 조작은 키가 같은 해시 슬롯에 있는 경우에 한정된다 ( 참고 ).
    이것에 대응하기 위해서는 타임 스탬프를 보존하는 키의 해시에 사용하는 캐릭터 라인을 큐의 키명으로 하면 된다.
    TIMESTAMP_KEY = "{#{QUEUE_KEY}}:updated_at".freeze
    
    CLUSTER KEYSLOT per_secCLUSTER KEYSLOT {per_sec}:updated_at 가 일치한다 = 같은 해시 슬롯에 저장되므로 MULTI - EXEC 를 사용할 수 있다.

    좋은 웹페이지 즐겨찾기