分布式锁(1) ----- 介绍和基于数据库的分布式锁

线程锁与分布式锁

1.java的synchronize和Lock都是属于线程锁,只能保证同一个进程内的多线程对共享变量修改访问同步。它们的原理都是设置一个可以让所有线程访问到标记,如synchronize是设置对象头的Mark Word,而Lock类是基于AQS的volatile修饰的state。

2.分布式锁是属于进程范畴的,而且进程可以在不同的机器上。它要保证的是多个进程对共享变量修改访问同步(例如集群环境下同时修改缓存和数据库)。分布式锁也同样需要一个可以让所有进程访问到的标记(如数据库的字段,redis的数据,zookeeper的节点等)来控制同步。

实现方法

1.基于数据库的分布式锁

2.基于redis的分布式锁

3.基于zookeeper的分布式锁

基于数据库的分布式锁

基于表主键唯一

利用主键具有唯一性的性质,加锁时向数据库插入以锁名为主键的数据,解锁时删除该数据。
优化:
1.没有过期时间,如果获得锁的服务解锁失败,将导致其他服务无法获得锁。网上也有解决方法:增加过期时间字段,定期清除过期锁数据。
2.重入性,增加获得锁服务的标记字段。

基于版本号字段

为表结构增加版本号字段,每次获取数据将版本号获取到,下次修改数据时判断当前版本是否该版本号。思路是与mysql的mvcc机制差不多的。

基于排他锁

public boolean lock(){
    connection.setAutoCommit(false)
    while(true){
        try{
            result = select * from lock where lockName=xxx for update;
            if(result==null){
                return true;
            }
        }catch(Exception e){

        }
        sleep(1000);
    }
    return false;
}

public void unlock(){
    connection.commit();
}

1.该方法是基于mysql的innodb的行级锁,所以lockName字段必须有索引存在,但因此也有一个问题,是否使用索引是有mysql来判断的,如果mysql认为全表查询更快,会使用表锁,那将会影响lock表的所有分布式锁。

2.for update会在执行失败是一直阻塞到成功。

优缺点

优点:容易实现理解

缺点:占用数据库连接,性能较低。

参考资料

https://www.cnblogs.com/seesun2012/p/9214653.html

原文地址:https://www.cnblogs.com/wuweishuo/p/10618609.html

时间: 2024-11-08 15:28:12

分布式锁(1) ----- 介绍和基于数据库的分布式锁的相关文章

基于数据库的分布式锁

使用场景: 某大型网站部署是分布式的,订单系统有三台服务器响应用户请求,生成订单后统一存放到order_info表:order_info表要求订单id(order_id)必须是唯一的,那么三台服务器怎么协同工作来确认order_id的唯一性呢?这时候就要用到分布式锁了. 分布式锁的要求: 在了解了使用场景之后,再看一下我们需要的分布式锁应该是怎样的(以方法锁为例) 这把锁要可重入(防止死锁) 这把锁最好是一个阻塞锁(根据业务考虑是否需要这条) 有高可用的获取锁跟释放锁的功能 获取锁跟释放锁的性能

谈谈分布式事务之二:基于DTC的分布式事务管理模型[下篇]

[续上篇] 当基于LTM或者KTM的事务提升到基于DTC的分布式事务后,DTC成为了本机所有事务型资源管理器的管理者:此外,当一个事务型操作超出了本机的范 围,出现了跨机器的调用后,本机的DTC需要于被调用者所在机器的DTC进行协助.上级对下级(包括本机DTC对本机所有资源管理器,以及上下级DTC) 的管理得前提是下级在上级那里登记,即事务登记(Transaction Enlist).所有事务参与者,包括所有资源管理器和事务管理器(即DTC)在进行了事务等级完成之后形成了一个树形的层级结构,该结

基于redis的分布式锁实现

关于分布式锁 很久之前有讲过并发编程中的锁并发编程的锁机制:synchronized和lock.在单进程的系统中,当存在多个线程可以同时改变某个变量时,就需要对变量或代码块做同步,使其在修改这种变量时能够线性执行消除并发修改变量.而同步的本质是通过锁来实现的.为了实现多个线程在一个时刻同一个代码块只能有一个线程可执行,那么需要在某个地方做个标记,这个标记必须每个线程都能看到,当标记不存在时可以设置该标记,其余后续线程发现已经有标记了则等待拥有标记的线程结束同步代码块取消标记后再去尝试设置标记.

python基于redis实现分布式锁

阅读目录 什么事分布式锁 基于redis实现分布式锁 一.什么是分布式锁 我们在开发应用的时候,如果需要对某一个共享变量进行多线程同步访问的时候,可以使用我们学到的锁进行处理,并且可以完美的运行,毫无Bug! 注意这是单机应用,后来业务发展,需要做集群,一个应用需要部署到几台机器上然后做负载均衡,大致如下图: 上图可以看到,变量A存在三个服务器内存中(这个变量A主要体现是在一个类中的一个成员变量,是一个有状态的对象),如果不加任何控制的话,变量A同时都会在分配一块内存,三个请求发过来同时对这个变

数据库实现分布式锁

数据库实现分布式锁 基于数据库实现分布式锁 上面已经分析了基于数据库实现分布式锁的基本原理:通过唯一索引保持排他性,加锁时插入一条记录,解锁是删除这条记录.下面我们就简要实现一下基于数据库的分布式锁. 表设计 CREATE TABLE `distributed_lock` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `unique_mutex` varchar(255) NOT NULL COMMENT '业务防重id', `holder_id` var

常用的分布式锁和redis和zk两种分布式锁的对比

常用的分布式锁 一..基于数据库实现分布式锁 1. 悲观锁 利用select … where … for update 排他锁 注意: 其他附加功能与实现一基本一致,这里需要注意的是“where name=lock ”,name字段必须要走索引,否则会锁表.有些情况下,比如表不大,mysql优化器会不走这个索引,导致锁表问题. 2. 乐观锁 所谓乐观锁与前边最大区别在于基于CAS思想,是不具有互斥性,不会产生锁等待而消耗资源,操作过程中认为不存在并发冲突,只有update version失败后才

quartz.net 基于数据库的简单实现

前面简单学习了通过XML配置或者内存指定的方式实现调度任务.但此用法实战用途较小,企业上多需要分布式集群的方式.quart团队也考虑到了这点,于是有了我们今天要学习的.基于数据库实现分布式. 1 NameValueCollection properties = new NameValueCollection(); 2 3 // 驱动类型,这里用的mysql,目前支持如下驱动: 4 //Quartz.Impl.AdoJobStore.FirebirdDelegate 5 //Quartz.Impl

数据库中乐观锁与悲观锁的概念

锁( locking ) 业务逻辑的实现过程中,往往需要保证数据访问的排他性.如在金融系统的日终结算 处理中,我们希望针对某个 cut-off 时间点的数据进行处理,而不希望在结算进行过程中 (可能是几秒种,也可能是几个小时),数据再发生变化.此时,我们就需要通过一些机 制来保证这些数据在某个操作过程中不会被外界修改,这样的机制,在这里,也就是所谓 的 " 锁 " ,即给我们选定的目标数据上锁,使其无法被其他程序修改. Hibernate 支持两种锁机制:即通常所说的 " 悲

基于SkyWalking的分布式跟踪系统 - 异常告警

通过前面2篇文章我们搭建了SW的基础环境,监控了微服务,能了解所有服务的运行情况.但是当出现服务响应慢,接口耗时严重时我们需要立即定位到问题,这就需要我们今天的主角--监控告警,同时此篇也是SW系列的最后一篇. UI参数 首先我们认识一下SW DashBoard上的几个关键参数,如下图所示 告警配置 告警流程 skywalking发送告警的基本原理是每隔一段时间轮询skywalking-collector收集到的链路追踪的数据,再根据所配置的告警规则(如服务响应时间.服务响应时间百分比)等,如果