Redlock实践--非阻塞模式

本文主要介绍在琴房预约项目中所用到的资源访问加锁技术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会直接报错终止程序

主要流程为:
  • 获取redis的操作权限
  • 设定键值,最长等待时间(防止一直被占用)
  • 执行操作
  • 释放锁
按照上面流程,我们成功进行了加锁。
键值的设置非常自由,我们可以通过键值的设置,控制加锁覆盖的范围以及力度。
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. 效果检验 Redlock实践--非阻塞模式
文章图片
加锁效果
在预约与检票单项测试的时候,1000个人中只有一个人成功,符合预期。
Redlock实践--非阻塞模式
文章图片
加锁效果
【Redlock实践--非阻塞模式】在预约与更改琴房可用时间混合测试的时候,2000个人中只有一个人成功,符合预期。
以上,说明这样加锁,可以成功解决资源访问竞争情况。
4. 参考资料
  1. redlock 效果解析
  2. redlock git地址

    推荐阅读