node.js 中使用redis实现分布式事务锁

在node项目中,我们常会跑一些定时任务,比如定时发送通知、定时发送邮件等,项目部署的时候,我们往往是多机多实例部署,这就导致每个实例都会跑一次同样的任务,所以我们需要一个分布式事务锁,来保证任务只能跑一次。

分布式事务锁

分布式事务锁有多种实现方式,大致分为以下几类

  • 基于数据库实现
  • 基于缓存(redis,memcached)
  • 基于Zookeeper

针对目前的需求,使用数据库锁太过于麻烦,Zookeeper目前生产未使用,而redis项目中刚好有使用,所以我们采取第二种实现方式

redLock

redis官方推荐了对应的解决方案 Redlock,官方中列出了各个语言的实现,其中有 node 的实现,如下连接

redLock-node实现

库中做了封装,使用起来非常简单

Configuration 配置

var client1 = require('redis').createClient(6379, 'redis1.example.com');
var client2 = require('redis').createClient(6379, 'redis2.example.com');
var client3 = require('redis').createClient(6379, 'redis3.example.com');
var Redlock = require('redlock');

var redlock = new Redlock(
	// you should have one client for each independent redis node
	// or cluster
	[client1, client2, client3],
	{
		// 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
	}
);
复制代码

Locking & Unlocking 锁事务和释放锁

// the string identifier for the resource you want to lock
var resource = 'locks:account:322456';

// the maximum amount of time you want the resource locked,
// keeping in mind that you can extend the lock up until
// the point when it expires
var ttl = 1000; // 锁的生存时间,在该时间内,若锁未释放,强行释放

redlock.lock(resource, ttl).then(function(lock) {

	// ...do something here...

	// unlock your resource when you are done
	return lock.unlock()
	.catch(function(err) {
		// we weren't able to reach redis; your lock will eventually
		// expire, but you probably want to log this error
		console.error(err);
	});
})
复制代码

通过以上方式,我们就可以实现分布式事务锁了

遇到的问题

在测试过程中,发现事务没有被锁住,一查,发现两台机子的系统时间不一致,有10秒左右的差别(测试伙伴因别的任务手动调整了时间),这就导致时间早的机子先跑了任务,时间慢的机子,在去获取锁的时候,锁早已经释放,所以RedLock 建立在了 Time 是可信的模型上 的。 这里推荐一篇文章 Redis RedLock 完美的分布式锁么? 解释的非常好

在别的博客看过一句话

分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”

优秀但不完美的方案在加上优秀的运维,定能够解决大部分的业务需求。

还有一个关于超时时间ttl的设定问题,到底是设定多长时间比较好,若设定太短,在任务还没执行完,锁就释放了,反之,如果设置的时间太长,其他获取锁的线程就可能要平白的多等一段时间,所以这个就要根据具体的业务场景来设定啦

小结

如果redis是使用单台的话,就没必要使用 redlock 这个方案,直接使用 setnx 设定一个标志位,就ok了

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值