liquibase和flyway中分布式锁实现的区别?

你们可能都知道,锁的存在本质上是为了解决共享资源互斥访问的问题,为了解决这个问题,在单机系统中(一个进程),不少开发语言都提供了锁的特性,好比说java的synchoronized、lock等;在分布式系统中(多个进程),则须要实现分布式锁,由于语言层面的锁特性不足以解决问题。php

关于分布式锁的概念、特性以及实现方式,网上有不少相关的文章,感兴趣的童鞋能够自行搜索。html

liquibase和flyway中分布式锁实现的区别?

简单讲,分布式锁也须要知足通常开发语言提供的锁的一些基本特性:java

* 互斥性:多个线程(可能位于不一样的进程上)访问共享资源时,同时只能有一个线程访问。redis

  • 阻塞性:一个线程访问共享资源时,其余线程应该被阻塞执行。数据库

  • 容错性:有机制防止死锁的发生,若是一个线程获得了锁,可是因为不正常退出(好比:宕机)致使锁没有显示释放,在这种状况下,须要有机制把这个锁释放掉,防止死锁发生。

如今常见的分布式锁的实现方案有:缓存

  • 基于数据库实现分布式锁架构

  • 基于缓存(redis,memcached etc.)实现分布式锁分布式

  • 基于Zookeeper实现分布式锁

...ide

上面分享了一些关于分布式锁的理论知识,接下来从liquibase和flyway两个library来解析它们实现分布式锁的区别。
liquibase和flyway中分布式锁实现的区别?memcached

有同窗可能知道,liquibase和flyway是数据库表结构改变的管理工具,这类工具的目的是使对数据库表结构的改变作到自动化,以防止人工对数据库表结构的改动带来的风险。两个工具的基本原理都相似,便是对数据库表结构的每一次改动维护成一条changeset(changeset能够是建立一个表,也能够是增长一个字段等),当应用程序启动时,会依次执行维护的changeset,一旦changeset被执行过,就不会被再执行,具体如何使用能够查看:

目前,这两个工具在不少项目中都有应用。

以前在项目(微服务架构)中,遇到过一个liquibase的问题:一个service用liquibase管理数据库change,有时候service在启动阶段忽然crash,再次启动,一直启动不起来,控制台一直看到以下日志:

INFO … Liquibase: Waiting for changelog lock....
INFO … Liquibase: Waiting for changelog lock....
INFO … Liquibase: Waiting for changelog lock....

在另一个场景,有时候也发现过相似的问题,一个service有两个instance,在第一个instance启动阶段,因为未知缘由忽然crash,这时候第二个instance再也启动不起来,控制台一样看到和上面同样的日志:

INFO … Liquibase: Waiting for changelog lock....
INFO … Liquibase: Waiting for changelog lock....
INFO … Liquibase: Waiting for changelog lock....

而一样的,有的service使用的flyway,却没有遇到过这样的问题。这是为何呢?

固然,在正常状况下,第一个service启动没问题,另一个service就会成功启动起来。

其实,上面这个场景是典型的一个分布式锁应用的场景:service的两个instance须要互斥访问数据库以执行changeset,第一个instance执行过程当中,第二个instance须要阻塞等待;第一个instance执行完了,会自动释放锁,接着第二个instance继续执行。

因为这两个library自己就是数据库相关的工具,自然就要依赖数据库,因此采用的分布式锁的实现方案就是基于数据库实现的方案。一般,基于数据库实现分布式锁有两种方式(参考https://blog.csdn.net/dingjianmin/article/details/82763871):

1.基于数据库表

2.基于数据库排他锁

两个library分别采用了这两种方式,Liquibase采用的是第一种-基于数据库表,Flyway采用的是第二种-基于数据库排他锁。

Liquibase维护了一张databasechangeloglock表来实现分布式锁。

Flyway则利用的是数据库的排他锁,以下图源码所示。(参考http://dbabullet.com/index.php/2018/03/29/best-practices-using-flyway-for-database-migrations/)

liquibase和flyway中分布式锁实现的区别?

采用第一种基于数据库表的实现方式,一个关键的问题就是,如何防止一个线程解锁失败,致使锁记录一直在数据库中,其余线程没法再得到到锁?而这个问题也就是上面项目中遇到的liquibase的问题,一个service instance忽然crash致使解锁失败,其余线程没法再得到到锁。

对于这个问题,liquibase官网只给出了一个workaround去清理脏锁,没有具体的计划fix这个问题。

liquibase和flyway中分布式锁实现的区别?

而因为flyway采起的是第二种基于数据库排他锁的方式,则不会有这个问题。由于基于数据库的排他锁,若是service忽然crash,service跟数据库的链接也就会断掉,加在表上的排他锁就会自动释放,进而接下来其余线程能够继续得到锁。

最后,针对分布式锁各类方案的解释,网上有不少写得挺好的文章,下面列出一些仅供参考:

  • 漫画:什么是分布式锁?

  • 漫画:如何用Zookeeper实现分布式锁?

  • 这才是真正的分布式锁

References

相关文章
相关标签/搜索