Redlock实践--非阻塞模式

2019-01-02  本文已影响0人  C3_b262

本文主要介绍在琴房预约项目中所用到的资源访问加锁技术Redlock,以及如果实现将redlock转为非阻塞锁。

1. 背景简介

1.1 项目简介

本次实践项目是THU琴房预约小程序与web管理端,后端使用koa框架。主要功能有预约琴房(用户)、更改琴房可用时间(管理端)等。后端使用mysql存储琴房信息(包含琴房可用时间串)。

1.2 问题介绍

根据上篇文章所描述的,因为存在不同操作之间的资源竞争,所以我们这里使用增加信号量的方式——Redlock。

2. 加锁实践

redlock是一个基于redis数据库的分布式锁。通过在redis数据库中设定键值来进行信号量的定义。

关于这个流程,包括set键值与”占用"和"未占用“状态的更改是由Redlock实现的。

2.1 给资源加锁

// 获取权限
let redis = require("redis");
let client = redis.createClient("to change: your redis port","to change: your server ip");
let redlock = new Redlock([client]);
// 设置时间
let totalTime = 5000;
let key = "to change: as you like";
// 加锁
redlock.lock(key, totalTime).then(async function(lock){
        // to do
        // your operation block
        // release lock
        lock.unlock().catch(function(err){})
    }
}).catch(()=>{}) // 如果不加catch会直接报错终止程序

主要流程为:

按照上面流程,我们成功进行了加锁。

键值的设置非常自由,我们可以通过键值的设置,控制加锁覆盖的范围以及力度。

2.2 阻塞锁与非阻塞锁

在完成加锁之后,我们进行压力测试,发现了一个非常坑的情况:Redlock是非阻塞锁

这就意味着,当一个用户进行预约的时候,别的用户如果有请求就会直接失败,这样是非常用户不友好的。所以我们需要一些操作来将redlock转为非阻塞锁。有两个方案:

对于方案一,请求队列可能会很长,如果前面的资源不释放,就会一直等待;对于方案二,轮询需要消耗更多的资源。

我们这里说明方案二的实现(目前最常用的转阻塞锁的方案)

let redis = require("redis");
let client = redis.createClient(config.redisPort,config.serverIp);
let redlock = new Redlock([client]);
let totalTime = 5000;
let key = "to change: as you like";
let intervalTime = 50;  // 轮询时间间隔

let sleep = function(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
}

let tag = 0;
for(let j = 0; j<200; j++){
    redlock.lock(key, totalTime).then(async function(lock){
        if(tag === 1){
            lock.unlock().catch(function(err){})
        }
        else{
            tag = 1
            // to do
            // your operation block
            // release lock
            lock.unlock().catch(function(err){})
        }
    }).catch(()=>{})
    if(tag === 1){
        break
    }
    await sleep(intervalTime) // 设置间隔时间
}
if(tag === 0){
    errorMsg = "请求超时"
    return ;
}

3. 效果检验

加锁效果

在预约与检票单项测试的时候,1000个人中只有一个人成功,符合预期。

加锁效果

在预约与更改琴房可用时间混合测试的时候,2000个人中只有一个人成功,符合预期。

以上,说明这样加锁,可以成功解决资源访问竞争情况。

4. 参考资料

  1. redlock 效果解析

  2. redlock git地址

上一篇下一篇

猜你喜欢

热点阅读