Files
ZYZ/game-server/app/services/redLockService.ts
2021-02-23 10:08:20 +08:00

106 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { localrun } from "pinus/lib/master/starter";
import { setLock, releaseLock, getLock } from './redlockCacheService';
var Redlock = require('redlock');
var _redlockCache;
export function initRedlock (redisClient) {
_redlockCache = new RedlockService(redisClient);
}
export class RedlockService {
_redisClient: any;
ttl: number;
redlock: any;
redlockNoRetry: any; // 用于检查锁是否存在,一锁上立刻会解锁
constructor(redisClient) {
this._redisClient = redisClient;
this._redisClient.on("error", function (err) {
console.error("Redis:Error:" + err);
});
this.ttl = 1000;
this.redlock = new Redlock(
[this._redisClient],
{
// the expected clock drift; for more details
// see http://redis.io/topics/distlock
driftFactor: 0.01, // time in ms
// the max number of times Redlock will attempt
// to lock a resource before erroring
retryCount: 10,
// the time in ms between attempts
retryDelay: 200, // time in ms
// the max time in ms randomly added to retries
// to improve performance under high contention
// see https://www.awsarchitectureblog.com/2015/03/backoff.html
retryJitter: 200 // time in ms
}
);
this.redlock.on('clientError', function(err) {
console.error('A redis error has occurred:', err);
});
this.redlockNoRetry = new Redlock(
[this._redisClient],
{
driftFactor: 0.01, // time in ms
retryCount: 0,
retryDelay: 200, // time in ms
retryJitter: 200 // time in ms
}
);
this.redlockNoRetry.on('clientError', function(err) {
console.error('A redis error has occurred:', err);
});
}
}
export async function lockData(serverId: number, dataName: string, id: string ) {
let key = 'serverId_'+serverId+'_'+dataName+'_'+id;
let lockKey = 'locks:' + key;
console.log(' lockKey = '+ lockKey);
return await lock(lockKey);
}
function lock(lockKey: string) {
return _redlockCache.redlock.lock(lockKey, _redlockCache.ttl).then(function(lock) {
setLock(lockKey, lock);
return {err: null, releaseCallback: releaseCallback.bind(null, lockKey)};
}).catch(function(err) {
console.error(err);
return { err };
});
}
export async function releaseCallback(lockKey: string) {
releaseLock(lockKey);
}
/**
* 主要用于检查是否锁定锁上后立刻会解锁所以entryCount为0
*
* @param serverId 区服
* @param dataName 锁名
* @param id 锁id
*/
export async function lockDataNoRetry(serverId: number, dataName: string, id: string ) {
let key = 'serverId_'+serverId+'_'+dataName+'_'+id;
let lockKey = 'locks:' + key;
console.log(' lockKey = '+ lockKey);
return await lockNoRetry(lockKey);
}
function lockNoRetry(lockKey: string) {
return _redlockCache.redlockNoRetry.lock(lockKey, _redlockCache.ttl).then(function(lock) {
setLock(lockKey, lock);
return {err: null, releaseCallback: releaseCallback.bind(null, lockKey)};
}).catch(function(err) {
console.error(err);
return { err };
});
}