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); } export async function lockDataWithNoParam(dataName: string) { let key = `${dataName}`; return await lock(key); } async function lock(lockKey: string) { return new Promise((resolve) => { _redlockCache.redlock.lock(lockKey, _redlockCache.ttl, function(err, lock) { if(err) { return resolve({ err }) } setLock(lockKey, lock); return resolve({err: null, releaseCallback: releaseCallback.bind(null, lockKey)}); }); }) } 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 }; }); }