手撕redis单实例分布式锁(node)

本文详细介绍了如何使用Node.js实现基于Redis的单实例分布式锁,包括应用场景如抢红包、抢票等,以及如何解决占位、死锁和网络闪断造成的问题。在实现过程中,利用setnx确保安全占位,设置过期时间防止死锁,并通过lua脚本来原子性地删除锁,确保数据一致性。
摘要由CSDN通过智能技术生成

应用场景

用于抢红包、抢票类似的服务,商城抢货。等场景中,对同一资源进行读写操作,避免不了的一个就是资源竞争问题,通过引入分布式锁这一概念,可以解决数据一致性问题。
注:
如果是redis集群,每个redis master节点都是独立存储的,这种场景用单实例会有安全性问题

redis分布式锁实现思路

实现分布式锁的方式有很多,类似: 数据库(mongo)、基于分布式协调系统(ZooKeeper)、缓存(redis)
基于redis分布式锁实现,需要保证3个特性:安全性、死锁、容错

  1. 安全性:
    一个萝卜一个坑,需要解决占位问题
  2. 死锁
    避免用户操作为处理,锁一直存在,价格过期时间
  3. 容错
    多节点情况下需要考虑的,只要能保证N/2+1节点可用,客户端就可以成功获取、释放锁(单实例不需要考虑,这种场景推荐redisLock依赖,开箱即用)

redis单实例实现过程

解决占位问题

对同一资源进行读写操作,避免不了的一个就是资源竞争问题,通过引入分布式锁这一概念,可以解决数据一致性问题。
方案
使用setnx 代替 set setnx key value

127.0.0.1:6379>
127.0.0.1:6379> get fg
(nil)
127.0.0.1:6379> SETNX fg 666
(integer) 1
127.0.0.1:6379> SETNX fg 777
(integer) 0
127.0.0.1:6379> get fg
"666"

解决死锁问题

为了防止用户拿到锁之后一直不处理所以设置过期时间,用户如果在一定时间内没有对这笔数据数据处理, 也会释放锁。
方案:
添加过期时间 expire key time

127.0.0.1:6379> setnx fg 666
(integer) 1
127.0.0.1:6379> expire fg 15
(integer) 1
127.0.0.1:6379> get fg
"666"
127.0.0.1:6379> ttl fg
(integer) 2
127.0.0.1:6379> get fg
(nil)
127.0.0.1:6379> ttl fg
(integer) -2
127.0.0.1:<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值