redsi分布式原子锁方案-单Redis实例实现分布式锁

分布式锁简介

同一时间只允许一个住户使用。
避免重复工作,避免破坏数据正确性。

分布式锁一些条件

  1. 互斥:仅一个客户端持锁。
  2. 防止死锁:保证客户端持锁崩溃等其他情况,也可主动释放。

死锁段子:在异地需要买火车票回老家,但是身份证丢了无法购票,补办身份证又需要本人坐火车回老家户籍管理处,就这样生活太难。

  1. 加锁、解锁必须同一客户端。
  2. 容错:大部分Redis节点正常,客户端就可获取和释放锁。

常见实现方式:

  1. 基于Redis
  2. 基于Mysql
  3. 基于Zookeeper

Redis

1. setnx和expire的非原子性

setnx刚执行成功,还未执行expire,节点1 挂掉,出现死锁。


image.png

2. set

  • set命令要用set key value px milliseconds nx;
  • value要具有唯一性;
  • 释放锁时要验证value值,不能误解锁;

set()得到2种结果:a,无锁,进行加锁操作,设置有效期。b,已锁不操作。

满足3个条件:互斥性:NX参数保证锁存在,不会二次调用。死锁:设置过期时间。容错性:暂考虑单机。


const IF_NOT_EXISTS = 'NX';
const MILLISECOND_EXPIRE_TIME = 'PX';
const LOCK_VALUE = 1;
//加锁
$redis->set($key, self::LOCK_VALUE , [self::IF_NOT_EXISTS, self::MILLISECOND_EXPIRE_TIME => $expire_time]);


$lua =<<eval($lua, array($key, self::LOCK_VALUE), 1);

Redis分布式锁常见问题

最大的缺点-Redis主从复制: 锁丢失
  • 案例:主从发生切换
    1. Redis在master拿到锁
    2. 加锁key没同步至slave
    3. master故障,主从迁移。slave升级为master
    4. 锁丢失
image.png
  • Redlock算法
    • 脑裂
    • 系统计时

参考文献

  • 解锁参考
  • Redis分布式锁-Redlock算法
  • 分布式: redlock-php

你可能感兴趣的:(redsi分布式原子锁方案-单Redis实例实现分布式锁)