RedLock- Distributed Locks with Redis

오픈소스·2023년 5월 10일
0
post-thumbnail

Redis Server

$ docker run --rm --name redis1 -p 6379:6379 redis
$ docker run --rm --name redis2 -p 6380:6379 redis
$ docker run --rm --name redis3 -p 6381:6379 redis

RedLock

const Redis = require("ioredis"); // 5.3.2
const { default: Redlock } = require("redlock"); // 5.0.0-beta.2

const redis1 = new Redis({
    port: 6379,
    host: "localhost",
})
const redis2 = new Redis({
    port: 6380,
    host: "localhost",
})
const redis3 = new Redis({
    port: 6381,
    host: "localhost",
})

const redlock = new Redlock(
    [redis1, redis2, redis3],
    {
        driftFactor: 0.01, // clock drift를 보상하기 위해 driftTime 지정에 사용되는 요소, 해당 값과 아래 ttl값을 곱하여 사용.
        retryCount: 10, // 에러 전까지 재시도 최대 횟수
        retryDelay: 200, // 각 시도간의 간격
        retryJitter: 200, // 재시도시 더해지는 되는 쵀대 시간(ms)
        automaticExtensionThreshold: 500, // lock 연장 전에 남아야 하는 최소 시간(ms)
    }
);

const paymentHistoryOfA = {
    pointRow: [5000]
}

const wait = (timeToDelay) => new Promise((resolve) => setTimeout(resolve, timeToDelay));

const getCurrentTotalPoint = async () => {
    await wait(200); // select 에 0.2ms 소요된다 가정
    return paymentHistoryOfA.pointRow.reduce((acc, cur) => (acc += cur), 0);
}

const addNewPointHistory = async (point) => {
    await wait(300); // insert 에 0.3ms 소요된다 가정
    paymentHistoryOfA.pointRow.push(point);
}

async function purchase(usagePoint) {
    try {
        console.log("redlock Starting...");
        let lock = await redlock.acquire(["a"], 5000);

        if (await getCurrentTotalPoint() >= usagePoint) {
            await addNewPointHistory(-1 * usagePoint);
            console.log('currentTotalPoint: ', await getCurrentTotalPoint());
        }
        await lock.release();
    } catch (err) {
        console.error("There was an error:", err.message);
    } finally {
        await redis1.disconnect();
        await redis2.disconnect();
        await redis3.disconnect();
    }
}

for (let i = 0; i < 10; i++) {
    purchase(3000);
}

redlock Starting...
redlock Starting...
redlock Starting...
redlock Starting...
redlock Starting...
redlock Starting...
redlock Starting...
redlock Starting...
redlock Starting...
redlock Starting...
currentTotalPoint: 2000
There was an error: The operation was unable to achieve a quorum during its retry window.
There was an error: The operation was unable to achieve a quorum during its retry window.
There was an error: The operation was unable to achieve a quorum during its retry window.
There was an error: The operation was unable to achieve a quorum during its retry window.
There was an error: The operation was unable to achieve a quorum during its retry window.
There was an error: The operation was unable to achieve a quorum during its retry window.
There was an error: The operation was unable to achieve a quorum during its retry window.
There was an error: The operation was unable to achieve a quorum during its retry window.
There was an error: The operation was unable to achieve a quorum during its retry window.

참고)

0개의 댓글