使用redis实现nodejs并发服务

Posted 与鲸同游

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用redis实现nodejs并发服务相关的知识,希望对你有一定的参考价值。

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)
        })
    })
}

 

以上是关于使用redis实现nodejs并发服务的主要内容,如果未能解决你的问题,请参考以下文章

Springboot使用redis的setnx和getset实现并发锁、分布式锁

redis基于redis实现分布式并发锁

Spring Data Redis两个问题:内存泄露和并发 - europace

nodejs express下使用redis管理session

golang代码片段(摘抄)

如何利用redis来进行分布式集群系统的限流设计