Files
llm-wiki/raw/company-tech-blogs/lock-subskribe-advisory-lock-distributed-consensus.md

10 KiB

title, source_type, url, archive_url, related_branches, related_projects, tags, created
title source_type url archive_url related_branches related_projects tags created
Leveraging Postgres Advisory Locks for Distributed Consensus — Subskribe Engineering Blog company-tech-blog https://www.subskribe.com/blog/leveraging-postgres-advisory-locks-for-distributed-consensus
feature-distributed-lock-contract
ca-skeleton-operational-contract
company-tech-blog
ca-skeleton-operational-contract
persistence
postgresql
advisory-lock
distributed-lock
company-case
2026-06-12

Leveraging Postgres Advisory Locks for Distributed Consensus — Subskribe Engineering Blog

Layer: raw/company-tech-blogs/ — 외부 기술 블로그 원문 발췌·출처 기록. 주의: 이 자료는 company-tech-blog 입니다. 특정 회사의 사례·관점이며, 공식 PostgreSQL 문서나 공식 best practice로 취급하지 않습니다.

Parent / 활용 branch

Branch 이 자료가 정당화하는 결정
raw/branch-notes/feature-distributed-lock-contract PostgreSQL advisory lock 의 production 사용 사례 — 추가 인프라 없이 DB 만으로 distributed mutual exclusion 을 달성한 사례 + "optimistic variant (try-lock) 만 사용, pessimistic blocking 은 비권장" 운영 교훈이 distributedLockProvider 메커니즘 비교의 사례 근거 (공식 best practice 아님 — 사례/관점으로만 취급)

출처 / Source

왜 저장했는지 / Why archived

feature-distributed-lock-contract 브랜치에서 distributedLockProvider 의 구현 메커니즘으로 PostgreSQL advisory lock 을 검토 중이며, Subskribe 가 동일 메커니즘을 production 에서 invoice 중복 생성 방지에 사용한 사례가 "추가 인프라 없이 advisory lock 만으로 distributed mutual exclusion 달성 가능 여부"를 뒷받침하는 사례 근거가 된다. 특히 "try-lock 만 사용하고 pessimistic blocking 은 쓰지 않았다"는 운영 결정이 ca-tmpl 의 tryLock 전용 contract 비교에 직접 활용된다.

핵심 인용 / Key quotes (verbatim, 5개)

[§Problem Statement] "at any given time you should generate only one invoice for a given subscription."

[§Advisory Locks API/Contract] "At Subskribe, we only use the optimistic variant (try to acquire lock and fail) of the advisory locks. Pessimistic locking (try to acquire lock but wait until you can or timeout) is, in general, not a good pattern, and we haven't seen much use for it in our engineering needs."

[§Why Advisory Locks] "PostgreSQL provides a means for creating locks that have application-defined meanings. This allows you to create locks on items that are not stored in the DB and mean something only to the application (e.g., locking on an arbitrary key that is stored only in application memory)."

[§WARNING] "If you acquire a session level lock from the application, it is the responsibility of the application to explicitly release that lock (otherwise the lock would be held). If you acquire a transaction level advisory lock, Postgres automatically releases the lock when the transaction ends ."

[§How Did It Solve the Problem] "We managed to achieve distributed mutual exclusion using Postgres advisory locks using only an arbitrary key (which is not even stored in the database)."

Claims Extracted / 추출된 주장

이 자료는 company-tech-blog 입니다. 아래 Claim 은 Subskribe 의 단일 사례이며, 공식 PostgreSQL 표준이나 업계 공통 best practice 를 증명하지 않습니다. advisory lock 의 동작 명세(session-level/transaction-level 해제 시맨틱 등)는 공식 PostgreSQL 문서(raw/official-docs/lock-postgres-advisory-locks)에서 별도 검증 필요.

Claim ID Claim (이 자료가 직접 말하는 것) Evidence quote Strength Applies to Does not prove
SUBSKRIBE-LOCK-C1 Subskribe 는 distributed mutual exclusion(invoice 중복 생성 방지)을 PostgreSQL advisory lock 만으로 달성했으며, 추가 인프라(Zookeeper, ETCD)를 사용하지 않았다 [§How Did It Solve the Problem] "We managed to achieve distributed mutual exclusion using Postgres advisory locks using only an arbitrary key (which is not even stored in the database)." company-case-study PostgreSQL DB 를 이미 사용하는 서비스에서 중복 실행 방지가 필요한 경우 PostgreSQL advisory lock 이 모든 분산 상호 배제 문제에 충분하다는 것, 대규모 트래픽에서의 성능·충돌률 데이터
SUBSKRIBE-LOCK-C2 Subskribe 는 advisory lock 중 optimistic variant(try-and-fail) 만 사용하며, pessimistic(blocking) locking 은 "not a good pattern" 으로 판단해 사용하지 않았다 [§Advisory Locks API/Contract] "At Subskribe, we only use the optimistic variant (try to acquire lock and fail) of the advisory locks. Pessimistic locking (try to acquire lock but wait until you can or timeout) is, in general, not a good pattern, and we haven't seen much use for it in our engineering needs." company-case-study advisory lock 기반 분산 락 구현 시 try-lock vs blocking 선택 결정 pessimistic locking 이 모든 시나리오에서 잘못됐다는 것; 이 주장은 Subskribe 엔지니어링 팀의 운영 경험 관점
SUBSKRIBE-LOCK-C3 advisory lock 은 DB 에 저장되지 않는 application-defined arbitrary key 에 대해 잠금을 획득할 수 있어, SELECT FOR UPDATE 와 달리 DB row 없이도 사용 가능하다 [§Why Advisory Locks] "PostgreSQL provides a means for creating locks that have application-defined meanings. This allows you to create locks on items that are not stored in the DB and mean something only to the application (e.g., locking on an arbitrary key that is stored only in application memory)." company-case-study lock key 가 DB row 가 아닌 application 레벨 개념(예: 구독 ID + 작업 context 문자열)인 경우 SELECT FOR UPDATE 와의 성능 비교 수치; PostgreSQL 내부 구현 명세(공식 문서 별도 확인 필요)
SUBSKRIBE-LOCK-C4 session-level advisory lock 은 애플리케이션이 명시적으로 해제해야 하며, transaction-level advisory lock 은 트랜잭션 종료 시 PostgreSQL 이 자동 해제한다 [§WARNING] "If you acquire a session level lock from the application, it is the responsibility of the application to explicitly release that lock (otherwise the lock would be held). If you acquire a transaction level advisory lock, Postgres automatically releases the lock when the transaction ends ." company-case-study advisory lock 의 session-level vs transaction-level 해제 시맨틱 설명 이 해제 시맨틱은 공식 PostgreSQL 문서에서 별도 검증 필요 — 이 문서는 사례 설명이지 공식 명세가 아님
SUBSKRIBE-LOCK-C5 Subskribe 는 문자열 key 를 advisory lock 의 bigint 인자로 변환하기 위해 Google Guava 의 SipHash(64-bit non-cryptographic hash)를 사용했다 [§Locking String Vs. Number] "We settled on the Sip Hash . This is a lesser known but very useful hash function of the 'add-rotate-xor' family , which is reasonably fast, has very good distribution properties, and a Guava implementation known to work well." company-case-study 문자열 lock key 를 bigint 로 해시해야 하는 구현 시 hash 함수 선택 사례 SipHash 가 이 용도의 유일한 정답이거나 collision-free 라는 것; hash collision 시 동작 보장 없음

Usage Boundaries / 적용 경계

  • 이 자료가 직접 증명하는 것:

    • SUBSKRIBE-LOCK-C1: PostgreSQL advisory lock 을 이미 사용 중인 단일 서비스(Subskribe)에서 invoice 중복 생성 방지에 적용한 사례
    • SUBSKRIBE-LOCK-C2: Subskribe 엔지니어링팀의 optimistic-only 운영 정책 ("try-and-fail 만, blocking 은 안 씀")
    • SUBSKRIBE-LOCK-C3: advisory lock 의 arbitrary key 특성 — DB row 필요 없음 (이는 공식 문서에서도 확인 가능한 사실이지만 이 자료는 사례 설명)
    • SUBSKRIBE-LOCK-C4: session-level vs transaction-level 해제 시맨틱 (공식 문서 별도 검증 필요)
    • SUBSKRIBE-LOCK-C5: SipHash를 사용한 string→bigint 변환 구현 사례
  • 이 자료가 증명하지 않는 것:

    • advisory lock 이 모든 규모·환경에서 distributed lock 의 공식 정답이라는 것
    • pessimistic locking 이 항상 나쁘다는 것 (이는 Subskribe 의 운영 판단)
    • pg_try_advisory_xact_lock 의 성능 수치·SLA 보장
    • hash collision 발생 시 동작 (SipHash 충돌 시 두 개의 다른 키가 같은 bigint 로 매핑될 수 있음)
    • ca-tmpl distributedLockProvider 구현 시 PostgreSQL advisory lock 이 Redis/ShedLock 대비 최선이라는 것
  • 내 프로젝트에 적용하려면 추가 확인이 필요한 것:

    • PostgreSQL advisory lock 의 session-level/transaction-level 해제 시맨틱은 공식 문서(raw/official-docs/lock-postgres-advisory-locks) 에서 재확인
    • ca-tmpl 의 JPA/HikariCP connection pool 환경에서 transaction-level advisory lock 이 Spring @Transactional 경계와 정합하는지 검증 필요
    • SipHash collision 허용 여부 — ca-tmpl lock key space 에서 collision 확률·영향도 검토

메모 / Notes

  • Subskribe 는 pg_try_advisory_xact_lock (transaction-level) 만 사용 — session-level(pg_try_advisory_lock) 은 명시적 해제 필요로 인해 connection pool 환경에서 "lock 해제 누락" 위험이 있음
  • 코드 전체가 공개되어 있으며(PostgresAdvisoryLock.java 전체 listing), Spring/jOOQ 기반 구현 사례로 ca-tmpl JPA 기반 구현과 직접 비교 가능
  • lock key 설계 패턴: <context>/<entity-id> (예: "invoice_gen/SUB-1234") — context prefix 를 붙여 동일 entity 에 대한 서로 다른 잠금 범위를 분리하는 패턴
  • 이 블로그 포스트의 자료 강도는 company-case-study — 공식 PostgreSQL 문서(raw/official-docs/lock-postgres-advisory-locks)와 함께 사용해야 결정 근거로서 완전함