Use redis achieve nodejs concurrent service

const redisClient = require('redis').createClient(6379, '127.0.0.1');
const crypto = require('crypto')

const lockScript = 'return redis.call("set", KEYS[1], ARGV[1], "NX", "PX", ARGV[2])'
const unlockScript = 'if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end'

redisClient.set("num","0")


for(let i=0;i<1000;i++) add()
for(let i=0;i<1000;i++) add()
for(let i=0;i<1000;i++) add()


async function add() {
    let resourse = "lock:num"
    let uniqueStr = crypto.randomBytes(10).toString('hex')

    await attemplock(resourse, uniqueStr)
    let nowCityNum = Number(await get('num'))
    num++
    await set('num', String(num))
    await unlock(resourse, uniqueStr)
}

async function loop(resourse, uniqueStr, ttl) {
    return new Promise((resolve, reject) => {
        setTimeout(async () => {
            let result = await lock(resourse, uniqueStr, ttl)
            resolve(!!result)
        }, 10)
    })
}

async function attemplock(resourse, uniqueStr, ttl) {
    let result = await loop(resourse, uniqueStr, ttl)
    if (result) {
        return true
    } else {
        return attemplock(resourse, uniqueStr, ttl)
    }
}

async function lock(resourse, uniqueStr, ttl) {
    ttl = ttl ? ttl : "30000"
    return new Promise((resolve, reject) => {
        redisClient.eval(lockScript, 1, resourse, uniqueStr, ttl, (err, reply) => {
            if (err) {
                console.error(err)
                reject(err)
            }

            resolve(reply)
        })
    })
}

async function unlock(resourse, uniqueStr) {
    return new Promise((resolve, reject) => {
        redisClient.eval(unlockScript, 1, resourse, uniqueStr, (err, reply) => {
            if (err) {
                console.error(err)
                reject(err)
            }

            resolve(reply)
        })
    })
}


async function get(key) {
    return new Promise((resolve, reject) => {
        redisClient.get(key, (err, reply) => {
            if (err) {
                console.error(err);
                reject(err)
            }
            resolve(reply)
        })
    })
}

async function set(key, value) {
    return new Promise((resolve, reject) => {
        redisClient.set(key, value, (err, reply) => {
            if (err) {
                console.error(err)
                reject(err)
            }
            resolve(reply)
        })
    })
}
async function setnx(key, value) {
    return new Promise((resolve, reject) => {
        redisClient.setnx(key, value, (err, reply) => {
            if (err) {
                console.error(err)
                reject(err)
            }
            resolve(reply)
        })
    })
}

 

Guess you like

Origin www.cnblogs.com/BlackFungus/p/12329521.html