Lock
Hyperf 原子鎖組件。
安裝
composer require friendsofhyperf/lock默認驅動使用 Redis。請根據使用的驅動安裝對應的可選依賴:
| 驅動 | 配置名稱 | 可選依賴 |
|---|---|---|
RedisLock | default | hyperf/redis |
FileSystemLock | file | hyperf/cache |
DatabaseLock | database | hyperf/db-connection |
CoroutineLock | co | 無 |
CacheLock | 未發佈 | hyperf/cache |
發佈配置文件:
php bin/hyperf.php vendor:publish friendsofhyperf/lock -i config使用數據庫驅動時,還需要發佈並執行鎖遷移:
php bin/hyperf.php vendor:publish friendsofhyperf/lock -i migrations
php bin/hyperf.php migrate運行發佈的遷移前,請將其中的 value 列改為 owner。當前 DatabaseLock 實現讀寫的是 owner 列。
配置
發佈的 config/autoload/lock.php 包含 default、file、database 和 co 配置。每項配置 用於選擇驅動類,並將其中的 constructor 選項傳給驅動。lock() 和 LockFactory::make() 的第四個參數是配置名稱,而不是驅動類名。
所選的 lock.<driver> 配置不存在時,工廠會拋出 InvalidArgumentException。你也可以新增 自定義配置,其驅動須實現 FriendsOfHyperf\Lock\Driver\LockInterface。
創建鎖
導入並調用帶命名空間的輔助函數:
use function FriendsOfHyperf\Lock\lock;
$lock = lock(name: 'foo', seconds: 10, owner: null, driver: 'default');
if ($lock->get()) {
try {
// The lock was acquired.
} finally {
$lock->release();
}
}不傳名稱調用 lock() 時返回 LockFactory,否則返回 LockInterface 實例。參數如下:
name:鎖名稱。seconds:請求的鎖有效期秒數,默認為0。owner:可選的所有者標識;省略時會隨機生成。driver:lock下的配置名稱,默認為default。
TTL 行為取決於驅動。特別是當 seconds 為 0 或負數時,DatabaseLock 會存儲一天的 過期時間。
鎖操作
LockInterface 公開 get()、block()、release()、owner()、forceRelease()、 refresh()、isExpired() 和 getRemainingLifetime()。
get() 只嘗試獲取一次;未傳回調時返回布爾值。傳入回調時,它會返回回調結果,並在 finally 塊中釋放鎖:
$result = lock('foo', 10)->get(function () {
return 'completed';
});block() 會重試,直到獲取鎖或達到等待時限;超時時拋出 LockTimeoutException。傳入回調 時也會自動釋放鎖:
use FriendsOfHyperf\Lock\Exception\LockTimeoutException;
try {
$result = lock('foo', 10)->block(5, function () {
return 'completed';
});
} catch (LockTimeoutException $exception) {
// The lock was not acquired within five seconds.
}release() 只釋放當前所有者持有的鎖,forceRelease() 會忽略所有權。僅當驅動支持時, refresh($ttl) 才能刷新過期時間;TTL 不為正數時返回 false。isExpired() 和 getRemainingLifetime() 返回鎖實例跟蹤的過期狀態。
註解
屬性注入
#[Lock] 用於屬性,並在應用啓動時注入鎖實例。參數為 name、seconds、owner 和 driver。
use FriendsOfHyperf\Lock\Annotation\Lock;
use FriendsOfHyperf\Lock\Driver\LockInterface;
class Foo
{
#[Lock(name: 'foo', seconds: 10, driver: 'default')]
protected LockInterface $lock;
}阻塞方法
#[Blockable] 用於方法。當 seconds 大於 0 時,它會創建鎖並最多等待 seconds 秒獲取 鎖,然後在方法返回或拋出異常後自動釋放。ttl 是鎖有效期,driver 用於選擇鎖配置。 prefix 和 value 會結合方法參數格式化為鎖名稱。
Blockable 使用 Hyperf\Cache\Helper\StringHelper,因此使用此註解前需安裝 hyperf/cache。
use FriendsOfHyperf\Lock\Annotation\Blockable;
class Foo
{
#[Blockable(prefix: 'user', value: '#{id}', seconds: 5, ttl: 30, driver: 'default')]
public function update(int $id): void
{
}
}