平時加鎖總是奔波於命名,害怕命名衝突,不規範等問題,於是使用debug_backtrace
函式通過呼叫鏈搞了一搞,通過file,class,function來確定一個鎖的位置,從而解決命名衝突,不規範等問題。(迎噴共近)
區域性鎖
對一段程式進行加鎖,保證該局域環境內或跨程式原子性,如傳送簡訊
public function sendSms(string $phone)
{
if (! setnxLock($phone, 10)) return false;
/**
* 處理邏輯
*/
delLock($phone);
return true;
}
全域性鎖
如一個訂單多個地方都在處理,但只能單一處生效
public function handleOrder(string $order_no)
{
if (! setnxLock($order_no, 10, true)) return false;
/**
* 處理邏輯
*/
delLock($order_no, true);
return true;
}
獲取快取鎖key
string getLockKey($key, true);
整理彙總
方法放在全域性方法中,方便全域性呼叫
<?php
use App\Constants\CacheKey;
if (! function_exists('setnxLock')) {
/**
* 設定快取鎖
*
* @param mixed $key 鎖鍵
* @param int $ttl 過期時間
* @param bool $global 是否全域性鎖
*
* @return bool
*/
function setnxLock($key, int $ttl = 5, bool $global = false): bool
{
$lock_key = getLockKey($key, $global);
return redis()->setnx($lock_key, 1) && redis()->expire($lock_key, $ttl);
}
}
if (! function_exists('delLock')) {
/**
* 刪除快取鎖
*
* @param mixed $key 鎖鍵
* @param bool $global 是否全域性鎖
*
* @return bool
*/
function delLock($key, bool $global = false): bool
{
$lock_key = getLockKey($key, $global);
return redis()->del($lock_key);
}
}
if (! function_exists('getLockKey')) {
/**
* 獲取快取鎖
*
* @param mixed $key 鎖鍵
* @param bool $global 是否全域性鎖
*
* @return string
*/
function getLockKey($key, bool $global = false): string
{
if ($global) return CacheKey::GLOBAL_LOCK_CACHE_KEY . $key;
return CacheKey::COMMON_LOCK_CACHE_KEY . md5(implode('', lockBacktrace())) . ':' . $key;
}
}
if (! function_exists('lockBacktrace')) {
/**
* 獲取呼叫位置
*
* @return array
*/
function lockBacktrace(): array
{
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)[4];
$file = $backtrace['file'] ?? '';
$class = $backtrace['class'] ?? '';
$function = $backtrace['function'] ?? '';
return compact('file', 'class', 'function');
}
}
快取key管理類
class CacheKey extends AbstractConstants
{
// 系統配置快取
const SYSTEM_CONFIG_CACHE_KEY = 'hash:system_config_cache';
// 全域性快取鎖
const GLOBAL_LOCK_CACHE_KEY = 'string:global_lock:';
// 普通快取鎖
const COMMON_LOCK_CACHE_KEY = 'string:common_lock:';
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結