작업 및 권고 잠금

이 게시물은 Postgres Advisory Lock을 활용하여 마이크로 서비스 간에 검사 가능한 비동기 작업 오케스트레이션을 생성하는 방법에 대해 설명합니다.

이름



최근에 나는 비동기적이고 내성적인 작업을 생성해야 하는 작업을 수행하게 되었습니다.

이제 이 문제는 새로운 것이 아닙니다. 실제로 정말 좋은 솔루션이 많이 있습니다. 이것은 kafka, mqs와 같은 도구를 사용하여 쉽게 달성할 수 있으며 심지어 이를 다음 단계로 가져가는 cadence와 같은 도구도 있습니다.

그러나 이것들은 모두 매우 좋은 솔루션이지만 너무 많을 수도 있습니다. 가지고 있는 것이 단일 postgres 인스턴스뿐이라면 어떻게 하시겠습니까? 글쎄요, 그게 제가 처한 상황이었고 해결책은 상당히 간단했습니다. 권고 잠금이었습니다!

더 진행하기 전에 제가 처한 상황을 설명하겠습니다.

상황



백그라운드에서 일부 프로세스를 완료해야 하는 사용자가 시스템에서 무언가를 요청한다고 가정해 보겠습니다.

1분이 걸릴 수도 있고, 1시간이 걸릴 수도 있고, 3개월이 걸릴 수도 있습니다. 작업이 아무리 오래 걸리더라도 응답이 즉시 반환될 수 없다는 것이 포인트입니다.

단순한 세상에서



이 예에서 사용자는 시스템에서 송장을 생성하도록 요청합니다.



작업 테이블에 데이터베이스 항목을 생성하는 것은 충분히 간단할 것입니다. 작업하는 동안 보류 상태에 있고 완료되면 삭제되거나 완료로 설정됩니다.

우리가 실제로 해야 할 일은 작업을 실행하는 시스템이 충돌하거나 중단된 경우 작업을 재개할 수 있는 것입니다.

그러나 우리는 마이크로서비스 환경에서 실행하고 있으며, 이는 단순했던 모든 것을 모험으로 만듭니다.

마이크로서비스 모험



이제 우리는 무엇을 해야 합니까? 동일한 작업을 동시에 수행하는 20개의 인스턴스를 원하지 않습니다.

실제로 "데이터베이스 항목 만들기"접근 방식은 여전히 ​​유효하지만 이제 프로세스가 다시 시작되면 보류 중인 작업 처리를 다시 시작해야 하는지 여부를 알아야 합니다.

물론 서비스가 충돌하면 "수령 가능"이라고 항목을 업데이트할 기회가 없습니다.

postgres를 사용하는 경우 간단한 해결책은 권고 잠금을 사용하는 것입니다.

권고 잠금



PostgreSQL provides a means for creating locks that have application-defined meanings. These are called advisory locks, because the system does not enforce their use — it is up to the application to use them correctly.



From Postgres Documentation

기본적으로 조언 잠금을 통해 수행할 수 있는 작업은 실제로 리소스를 잠그지 않고 플래그를 만드는 것입니다.

트랜잭션 수준 권고 잠금의 경우 다음과 같은 경우 잠금이 사라집니다.
A. 트랜잭션 커밋
B. 트랜잭션 롤백(클라이언트 연결 해제 포함)

다른 작업에서 테이블을 사용하지 못하도록 테이블을 실제로 잠그고 싶지 않기 때문에 이것은 우리에게 좋습니다. 또한 프로세스가 충돌하면 권고 잠금이 사라짐을 의미합니다.

활용 방법은 다음과 같습니다.



이것은 멋져 보이지만 실제로는 채워야 할 몇 가지 간격이 있습니다.

그중 하나는 각 권고 잠금에 식별자로 bigint가 필요하다는 것입니다.

사용자 ID가 이미 int인 경우에는 문제가 되지 않습니다(네임스페이스만 원할 수 있음).
KSUID 또는 UUID와 같은 ID인 경우 int로 해시해야 합니다. 이미 많은 기존 소스가 있으므로 이에 대해서는 다루지 않겠습니다.

아래 쿼리를 사용하여 트랜잭션 수준 잠금을 만들 수 있습니다.

SELECT pg_try_advisory_xact_lock(42) -- 42 is the User ID


잠금이 있는지 확인하는 쿼리는 다음과 같습니다.

SELECT granted FROM pg_locks WHERE locktype = 'advisory' AND objid = '42' -- 42 is the LockID which is our User ID


재시작 시 재개



마지막으로 남아 있는 작업은 시작 시 기존 작업을 선택하는 것입니다.

이렇게 보일 수 있습니다.



기본적으로 다시 시작할 때 보류 중인 작업에 대해 데이터베이스를 쿼리하고 해당 작업에 대한 권고 잠금이 있는지 확인합니다. 하나도 없다면 아무도 처리하지 않는다는 의미이므로 가져가야 합니다!

그게 다야!



이것이 단순하고 비동기적이며 상호 운용 가능한 작업을 생성하는 데 필요한 전부입니다.

좋은 웹페이지 즐겨찾기