30 如何使用Redis实现分布式锁? 基本概念 单机上

基本概念

  • 什么是分布式锁
+ 如果需要控制分布式系统,不能是某个客户端本地的锁
+ 锁是保存在一个共享存储系统中的,可以被多个客户端共享访问和获取\
  • 为什么选择redis
+ 可以被多个客户端共享访问,正好就是一个共享存储系统\
+ 读写性能高,可以应对高并发的锁操作场景

单机上的锁和分布式锁的联系与区别

  • 对于单机锁
+ 变量为0,表示线程未获取到锁
+ 变量为1,表示已经有线程获取到锁
+ 获取锁则把变量置为1
+ 释放锁则把变量置为0
  • 分布式锁
+ 也是通过判断锁的变量值,多个客户端存储数据
+ 新的要求


    - 分布式锁的加锁和释放锁的过程,涉及多个操作(需要保证原子性)\
    - 怎么保证分布式锁的稳定性和可靠性

基于单个 Redis 节点实现高可靠的分布式锁

  • 设置设计分布式锁
+ key锁的名称 value锁的状态
  • 怎么保证读取锁,判断锁和设置锁操作的原子性
+ 使用redis原子命令


    - SETNX 如果存在就设置,如果不存在就不设置+DEL删除释放锁\
+ 使用Lua脚本
  • 使用SETNX的潜在风险
+ DEL操作异常,导致锁一直不释放  通过设置过期时间避免死锁
+ 不是申请的锁的客户端执行DEL会误删除锁 可以将value设为客户端唯一值
+ SET 命令的 NX 和 EX/PX 选项\
  • DEL删除释放锁\
+ 最好使用lua脚本,保证指令的原子性
+ 读取数据,删除释放数据

\

基于多个 Redis 节点实现高可靠的分布式锁

  • Redis 的开发者 Antirez 提出了分布式锁算法 Redlock\
  • 如果客户端能够和半数以上的实例成功地完成加锁操作\
+ 获取锁成功
+ 否则获取锁失败
  • 具体实现步骤
+ 客户端获取当前时间
+ 客户端按顺序依次向 N 个 Redis 实例执行加锁操作(使用指令SETNX value是客户端标识) 顺序加锁\
+ 完成加锁,计算总耗时 判断是否成功


    - 超过半数加锁成功
    - 总耗时未超过过期时间
  • 可以通过redlock保证可靠性

总结

  • 加锁注意点
+ 加锁包括了读取锁变量、检查锁变量值和设置锁变量值三个操作 使用SETNX指令\
+ 锁变量需要设置过期时间,避免死锁\
+ 锁变量的值需要能区分来自不同客户端的加锁操作,以免在释放锁时,出现误释放操作\
  • 释放锁注意点
+ 释放锁也包含了读取锁变量值、判断锁变量值和删除锁变量三个操作\
+ 没有指令能够完成
+ 一般使用lua脚本实现操作的原子性
  • 保证稳定性
+ 可以使用Redlock算法,实现基于多个实例的分布式锁

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%