pglock v0.2.1
https://github.com/myyrakle/pglock
์ฌ๋ฌ ๋
ธ๋์ ๊ฑธ์ณ์ ์ฌ์ฉํ ๋ถ์ฐ ๋ฝ์ด ํ์ํ๋๋ฐ, Redis๋ฅผ ๊ตณ์ด ์ถ๊ฐํด์ ๋ถ์ด๊ธฐ๋ ์ซ์ด์ PostgreSQL ๊ธฐ๋ฐ์ผ๋ก ๋ฒ์ฉ์ ์ธ ๊ตฌํ์ฒด๋ฅผ ํ๋ ๋ง๋ค์ด๋ดค๋ค.
์ฌ์ฉ๋ฒ์ ๊ฐ๋จํ๋ค.
์ผ๋จ ๋ชจ๋์ ์ค์นํ๋ค.
go get github.com/myyrakle/pglock@v0.2.1
๊ทธ๋ฆฌ๊ณ ์ด๋ฐ ์์ผ๋ก ํด๋ผ์ด์ธํธ ์ด๊ธฐํํด์ ์ฐ๋ฉด ๋๋ค.

๊ทธ๋ผ ์ intiailze ๊ณผ์ ์์ lock ํ ์ด๋ธ์ ์๋์ผ๋ก ๋ง๋ ๋ค.
์์ฑ๋๋ ํ
์ด๋ธ์ ์ด๋ฆ์ ์ต์
LockTableName์ ํตํด ์ปค์คํ
ํ ์ ์๋ค.
๊ธฐ๋ณธ๊ฐ์ ๊ทธ๋ฅ lock์ด๋ค.
XLock
XLock์ ๋์์ ํ๋๋ง ์ ์ ํ ์ ์๋ ๋ถ์ฐ ๋ฝ ๊ตฌํ์ด๋ค.
๋์ ์๋ฆฌ ์์ฒด๋ Mutex์ ๋ค๋ฅผ ๋ฐ ์๋ค.
๋์์ ํ๋์ ์ฌ์ฉ์๋ง ๋์ผํ Lock์ ์ ์ ํ ์ ์๊ณ , Lock ์ ์ ์ ์คํจํ ๊ฒฝ์ฐ ๋ด๋ถ์ ์ผ๋ก TryXLock ๋ฃจํ๋ฅผ ๋๋ฉด์ ๋ธ๋ญํ๋ค.
์๋๋ ๊ฐ๋จํ ์์ ๋ค. ๊ณ ๋ฃจํด์ 5๊ฐ ๋์์ Lock์ ๊ฒฝ์ํ๋ค.

package main
import (
"context"
"fmt"
"log"
"sync"
"github.com/myyrakle/pglock"
)
func main() {
lockClient := pglock.NewLockClient(pglock.LockClientOptions{
DatabaseURL: "postgres://postgres@localhost:5432/postgres?sslmode=disable",
})
if err := lockClient.Initialize(); err != nil {
log.Fatal(err)
}
ctx := context.Background()
wg := sync.WaitGroup{}
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
log.Printf("Goroutine %d: Attempting to acquire lock...", i)
_, err := lockClient.XLock(ctx, pglock.XLockParams{
Name: "test_lock",
LockID: fmt.Sprintf("test_lock_%d", i),
TTLSeconds: 60,
})
if err != nil {
log.Printf("Goroutine %d: Failed to acquire lock: %v", i, err)
return
}
log.Printf("Goroutine %d: Lock acquired!", i)
// Simulate some work with the lock held
// time.Sleep(2 * time.Second)
if _, err := lockClient.Unlock(ctx, pglock.UnlockParams{
Name: "test_lock",
LockID: fmt.Sprintf("test_lock_%d", i),
}); err != nil {
log.Printf("Goroutine %d: Failed to release lock: %v", i, err)
return
}
log.Printf("Goroutine %d: Lock released!", i)
}(i)
}
wg.Wait()
log.Println("All goroutines have finished.")
}
์ค์ ๋ก๋ ์คํํด๋ณด๋ฉด Lock์ ๊ธฐ๋ฐ์ผ๋ก ์ค์ ์ด์ ๋ง์ถ๋ฉด์ ๋์ํ๊ฒ ๋๋ค.

์ ์ํ ๋ถ๋ถ์ Unlock๊ณผ TTL์ด๋ค.
ํญ์ Unlock๊น์ง ์ฑ
์์ ธ์ ๋ง๋ฌด๋ฆฌํด์ค์ผ ํ๊ณ , ํน์๋ Lock์ ์ก์์ฑ๋ก ์ฃฝ์ด๋ฒ๋ฆด ๊ฒฝ์ฐ๋ฅผ ๋๋นํด์ TTL ํ๋๊ทธ๋ ์๋ค. TTL์ด ์ง๋๋ฉด Lock์ด ๋จ์์๋๋ผ๋ ํ๋ฆฐ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ๊ณ ์ฌ์ง์
์ด ๋๋ค.
SLock
SLock - Shared Lock์ ์ข ๋ ์ ์ฐํ ๋ฒ์ ์ ๊ตฌํ์ฒด๋ค.
๋์์ ์ ๊ทผ ๊ฐ๋ฅํ ๋ฆฌ์์ค๋ฅผ ์ํ๋๋๋ก ์กฐ์ ํ ์ ์๋ค. ์ธ๋งํฌ์ด์ ๋น์ทํ๋ค.
์ ๋ฐ์ ์ธ ์ฌ์ฉ๋ฒ์ด๋ ์๋ฆฌ๋ XLock๊ณผ ๋ค๋ฅด์ง ์์ผ๋, ๋์ ์ ๊ทผ ์๋ฅผ ์ง์ ํ ์ ์๋ค๋ ๊ฒ์ด ๋ค๋ฅด๋ค.
-1๋ก ์ค์ ํ๋ฉด ๋ฌด์ ํ์ผ๋ก ๋ค์ด์ฌ ์ ์๊ณ , ์ ๋ ๊ฒ 2๋ฅผ ๋ฃ์ผ๋ฉด ์ต๋ 2๊ฐ์ ์ฌ์ฉ์๊ฐ Lock์ ๋์์ ์ก์ ์ ์๋ค.
๊ทธ๋์ ์ ๋๋ก ์คํํ๋ฉด
์ต๋ 2๊ฐ๊น์ง๋ง ๋ค์ด์๋ค๊ฐ ๋๊ธฐํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ XLock๊ณผ SLock์ ์ํธ๋ฐฐํ์ ์ด๋ค.
SLock์ ์ก์ ์ํ์์๋ XLock์ด ๋ค์ด์ฌ ์ ์๊ณ , XLock์ ์ก์ ์ํ์์๋ SLock์ด ๋ค์ด์ฌ ์ ์๋ค.
๊ธฐ๋ฅ ์ ๋ฆฌ๋ ์ต์ ํ ์ข ํ๊ณ , ์ฐ์ ์์ ๋ฝ๋ ๊ตฌํํด๋๊น ์ถ๋ค.