什么是分布式锁?

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
简介: 什么是分布式锁?

什么是分布式锁?

在一些分布事场景下,为了保证数据的一致性,而分布式锁就是用来解决这个问题的。例如,当多台机器需要对同一个用户属性进行修改时,就会出现属性值跟预想的不一样的结果,如下图所示:

e448b4c00473cd995486ae71a8d917d1.png PS:其实跟多线程锁需要解决的问题很像——都是为了达到数据的一致性。只不过多线程锁是为了解决单机问题,而分布式锁是为了解决多台机器(分布式集群)的问题。

分布式锁应该具备的条件:

  • 一个方法同一时间只能被一台机器执行;
  • 高可用的获取锁和释放锁;
  • 高性能的获取锁和释放锁;
  • 具备可重入性;
  • 具备相应的机制,防止死锁;

三种分布式锁的实现

有三种实现分布式的方式,分别是:

  • 基于数据库;
  • 基于缓存(Redis);
  • 基于Zookeeper;

基于数据库

这种方式的核心思想是:在数据库中创建一个表,表中包含方法名等字段,并在方法名字段上创建唯一索引,想要执行某个方法,就使用这个方法名向表中插入数据,成功插入则获取锁,执行完成后删除对应的行数据释放锁。

PS:唯一索引是啥?这应该不用解释了。

这种方式的问题:

  • 数据库的可用性和性能直接影响分布式锁,因此数据库需要双机部署、数据同步等;
  • 不具备可重入,因为同一行数据只能存在一个;
  • 没有锁失效的机制;
  • 为了阻塞锁等方式,实现方式比较复杂;

基于缓存(Redis)

Redis实现分布式锁的方式的核心就是:Redis性能较好,而且内置分布式锁命令

具体步骤:

  • 获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断
  • 获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
  • 释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放

这种方式也有缺点:

Redis的性能很好,但是无论是单机还是主从备换模式都可能会造成锁丢失

基于Zookeeper

Zookeeper**是一个专门为分布式应用提供一致性服务的开源组件,**内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名,步骤如下:

  • 创建一个目录mylock
  • 线程A想获取锁就在mylock目录下创建临时顺序节点;
  • 获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁
  • 线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点
  • 线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。

缺点就在于:

需要频繁的创建和删除节点,性能不如Redis

总结

分布式的CAP理论表明——任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)。因此没有一种方式可以使得分布式锁完美无缺,具体使用什么方式来实现分布式锁,都应根据不同的应用场景选择最适合的实现方式。

参考链接

什么是分布式锁?

Redis与Zookeeper的分布式锁

相关文章
|
SQL 关系型数据库 Go
PostgreSQL 查询语句大全
PostgreSQL 查询语句大全
233 0
|
4月前
|
设计模式 网络协议 Java
【设计模式】【行为型模式】状态模式(State)
一、入门 什么是状态模式? 状态模式(State Pattern)是一种行为设计模式,允许对象在其内部状态改变时改变其行为,使其看起来像是改变了类。状态模式的核心思想是将对象的状态封装成独立的类,并将
194 16
|
Arthas Java 测试技术
超好用的自带火焰图的 Java 性能分析工具 Async-profiler 了解一下
超好用的自带火焰图的 Java 性能分析工具 Async-profiler 了解一下
2705 0
超好用的自带火焰图的 Java 性能分析工具 Async-profiler 了解一下
|
2月前
|
监控 安全 Java
SpringBoot应用-Actuator监控
Spring Boot Actuator 是 Spring Boot 提供的一个独立模块,旨在通过简单的方式提供应用程序的监控和管理功能。Actuator 内置了多种端点(Endpoints),可以用于查看应用的健康状况、配置属性、日志级别等。
584 1
|
4月前
|
缓存 Java 数据库连接
Mybatis一级缓存详解
Mybatis一级缓存为开发者提供跨数据库操作的一致性保证,有效减轻数据库负担,提高系统性能。在使用过程中,需要结合实际业务场景选择性地启用一级缓存,以充分发挥其优势。同时,开发者需注意其局限性,并做好事务和并发控制,以确保系统的稳定性和数据的一致性。
143 20
|
Java 数据库连接 Maven
如何使用Sentinel实现流控和降级
通过以上步骤,你可以使用Sentinel实现应用的流量控制和降级操作,以保护系统在高流量或不稳定情况下的稳定性。欢迎关注威哥爱编程,一起学习成长。
379 1
|
9月前
|
调度 数据库
什么场景下要使用分布式锁
分布式锁用于确保多节点环境下的资源互斥访问、避免重复操作、控制并发流量、防止竞态条件及任务调度协调,常见于防止超卖等问题。
253 4
|
10月前
|
Arthas Prometheus 监控
监控堆外使用JVM工具
监控堆外使用JVM工具
265 7
|
10月前
|
缓存 NoSQL 中间件
redis高并发缓存中间件总结!
本文档详细介绍了高并发缓存中间件Redis的原理、高级操作及其在电商架构中的应用。通过阿里云的角度,分析了Redis与架构的关系,并展示了无Redis和使用Redis缓存的架构图。文档还涵盖了Redis的基本特性、应用场景、安装部署步骤、配置文件详解、启动和关闭方法、systemctl管理脚本的生成以及日志警告处理等内容。适合初学者和有一定经验的技术人员参考学习。
724 7
|
消息中间件 关系型数据库 MySQL
SpringBoot-Kafka(生产者事务、手动提交offset、定时消费、消息转发、过滤消息内容、自定义分区器、提高吞吐量)
SpringBoot-Kafka(生产者事务、手动提交offset、定时消费、消息转发、过滤消息内容、自定义分区器、提高吞吐量)
SpringBoot-Kafka(生产者事务、手动提交offset、定时消费、消息转发、过滤消息内容、自定义分区器、提高吞吐量)