跳转到主要内容

使用PostgreSQL咨询锁实现简单的分布式锁定。

项目描述

https://circleci.com/gh/level12/pals.svg?style=shield https://codecov.io/gh/level12/pals/branch/master/graph/badge.svg

介绍

PALs使得使用PostgreSQL咨询锁进行分布式应用程序级锁定变得简单。

不要将此类锁定与PostgreSQL中的表或行锁定混淆。它们不是同一回事。

可以通过使用Redis、Memcache、ZeroMQ等方式实现分布式应用程序级锁定。但对于已经使用PostgreSQL的用户,设置和管理另一个服务是不必要的。

用法

安装

pip install PALs

然后使用方法如下

import datetime as dt
import pals

# Think of the Locker instance as a Lock factory.
locker = pals.Locker('my-app-name', 'postgresql://user:pass@server/dbname')

lock1 = locker.lock('my-lock')
lock2 = locker.lock('my-lock')

# The first acquire works
assert lock1.acquire() is True

# Non blocking version should fail immediately
assert lock2.acquire(blocking=False) is False

# Blocking version should fail after a short time
start = dt.datetime.now()
acquired = lock2.acquire(acquire_timeout=300)
waited_ms = duration(start)

assert acquired is False
assert waited_ms >= 300 and waited_ms < 350

# Release the lock
lock1.release()

# Non-blocking usage pattern
if not lock1.acquire(blocking=False):
    # Aquire returned False, indicating we did not get the lock.
    return
try:
    # do your work here
finally:
    lock1.release()

# If you want to block, you can use a context manager:
try:
    with lock1:
        # Do your work here
        pass
except pals.AcquireFailure:
    # This indicates the aquire_timeout was reached before the lock could be aquired.
    pass

文档

只是这个readme文件、代码和测试。这是一个小型项目,应该很容易理解。

请随时提出问题。

本地运行测试

设置数据库连接

我们提供了一个docker-compose文件来简化测试的运行

$ docker-compose up -d
$ export PALS_DB_URL=postgresql://postgres:password@localhost:54321/postgres

运行测试

使用tox

$ tox

或者,手动(假设已激活的虚拟环境)

$ pip install -e .[tests]
$ pytest pals/tests/

锁定释放和过期

与建立在缓存服务(如Memcache和Redis)之上的锁定系统不同,这些服务的键可以被服务过期,PostgreSQL中没有过期建议锁的能力。如果一个客户端持有锁然后休眠/挂起几分钟/几小时/几天,没有其他客户端能获取那个锁,直到客户端释放它。这对我们来说实际上是一件好事,如果获取了锁,就应该保持直到释放。

但关于意外未释放锁的情况怎么办呢?

  1. 如果开发人员使用了lock.acquire()但没有随后调用lock.release()呢?

  2. 如果锁内的代码意外抛出异常(并且没有调用.release())?

  3. 如果运行应用程序的进程崩溃或进程的服务器关闭?

PALs以几种不同的方式帮助解决上述1和2中的问题。

  • 锁作为上下文管理器工作。尽可能多地使用它们,以确保锁被释放。

  • 锁在垃圾回收时释放其锁。

  • PALs使用专用的SQLAlchemy连接池。当连接返回到池中时,无论是由于调用.close()还是由于连接的垃圾回收,PALs都会发出pg_advisory_unlock_all()。因此,空闲连接池中不应再保留任何持有的锁。

关于上述3,pg_advisory_unlock_all()在连接(即会话)结束时被PostgreSQL隐式调用,即使客户端不优雅地断开连接。因此,如果一个进程崩溃或以其他方式消失,PostgreSQL应该注意到并删除该连接/会话持有的所有锁。

可能存在这样的情况:PostgreSQL没有检测到连接已关闭并无限期地保留锁。然而,在手动测试中使用scripts/hang.py没有找到一种方法可以结束Python进程而不让PostgreSQL检测到。

另请参阅

更改日志

0.4.0发布于2024-04-16

  • 支持psycopg3,向后兼容psycopg2(感谢@petr.prikryl)(0139bea

  • 从CI中移除python 3.7和3.8,解决flake8问题(24bff1f

0.3.5发布于2023-06-29

  • 修复连接关闭后的游标使用(感谢@moser)(ded88e7

0.3.4发布于2023-03-06

  • 支持SQLAlchemy 2.0(《6879081》)

0.3.3发布于2023-01-06

  • 向AcquireFailure异常添加附加信息(《6d81db9”)

0.3.2发布于2021-02-01

  • 支持共享建议锁(感谢@absalon-james)(《ba2fe21”)

0.3.1发布于2020-09-03

  • readme:更新postgresql链接(《260bf75”)

  • 处理DB连接已返回到池中但已关闭的情况(《5d730c9”)

  • 修复注释中的几个错误(《da2b8af”)

  • readme改进(《4efba90”)

  • CI:修复覆盖率上传(《52daa27”)

  • 修复CI:将CI python提升到v3.7和postgres提升到v11(《23b3028”)

0.3.0发布于2019-11-13

增强

  • 在Locker级别添加获取超时和阻塞默认值(《681c3ba”)

  • 将默认锁超时从1秒调整为30秒(《5a0963b”)

项目清理

  • 调整flake8忽略和其他tox项目警告(《ee123fc”)

  • 修复测试中的注释(《0d8eb98”)

  • 其他readme更新(《0786766”)

  • 更新锁定依赖(《f5743a6”)

  • 从CI中移除Python 3.5 (b63c71a)

  • 整理了readme代码示例并添加了更多引用 (dabb497)

  • 更新setup.py以使用SPDX许可证标识符 (b811a99)

  • 移除Pipefiles (0637f39)

  • 改为使用piptools进行依赖管理 (af2e91f)

0.2.0版本发布于2019-03-07

  • 修复“acquire”的拼写错误 (737763f)

0.1.0版本发布于2019-02-22

  • 使用lock_timeout设置来使阻塞调用过期 (d0216ce)

  • 修复tox (1b0ffe2)

  • 重命名为PALs (95d5a3c)

  • 改进readme (e8dd6f2)

  • 将测试文件移动到更好的位置 (a153af5)

  • 添加flake8依赖 (3909c95)

  • 修复测试以使其在本地也能工作 (7102294)

  • 使circleci工作 (28f16d2)

  • 在Lock __del__中抑制异常 (e29c1ce)

  • 添加hang.py脚本 (3372ef0)

  • 修复打包问题,更新readme (cebd976)

  • 初始提交 (871b877)

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

PALs-0.4.0.tar.gz (14.8 kB 查看哈希)

上传时间

构建分布

PALs-0.4.0-py2.py3-none-any.whl (9.6 kB 查看哈希)

上传时间 Python 2 Python 3

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面