[Qiji y Qiao] solve the problem of difficult naming and naming conflict of program cache lock

Time:2021-11-30

Usually, locking is always about naming, afraid of naming conflicts, non-standard and other problems, so it is useddebug_backtraceThe function makes a mess through the call chain, and determines the position of a lock through file, class and function, so as to solve the problems of naming conflict and non-standard. (approaching the jet)

Local lock

Lock a program to ensure atomicity within or across processes in the local environment, such as sending short messages

public function sendSms(string $phone)
{
    if (! setnxLock($phone, 10)) return false;
    /**
     *Processing logic
     */
    delLock($phone);

    return true;
}

Global lock

For example, an order is processed in multiple places, but it can only take effect in a single place

public function handleOrder(string $order_no)
{
    if (! setnxLock($order_no, 10, true)) return false;
    /**
     *Processing logic
     */
    delLock($order_no, true);

    return true;
}

Get cache lock key

string getLockKey($key, true);

Collate and summarize

Method is placed in the global method to facilitate global calling

<?php

use App\Constants\CacheKey;

if (! function_exists('setnxLock')) {
    /**
     *Set cache lock
     *
     *@ param mixed $key lock key
     *@ param int $TTL expiration time
     *@ param bool $global whether global lock
     *
     * @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')) {
    /**
     *Delete cache lock
     *
     *@ param mixed $key lock key
     *@ param bool $global whether global lock
     *
     * @return bool
     */
    function delLock($key, bool $global = false): bool
    {
        $lock_key = getLockKey($key, $global);

        return redis()->del($lock_key);
    }
}

if (! function_exists('getLockKey')) {
    /**
     *Get cache lock
     *
     *@ param mixed $key lock key
     *@ param bool $global whether global lock
     *
     * @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')) {
    /**
     *Get call location
     * 
     * @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');
    }
}

Cache key management class

class CacheKey extends AbstractConstants
{
    //System configuration cache
    const SYSTEM_CONFIG_CACHE_KEY = 'hash:system_config_cache';
    //Global cache lock
    const GLOBAL_LOCK_CACHE_KEY = 'string:global_lock:';
    //Normal cache lock
    const COMMON_LOCK_CACHE_KEY = 'string:common_lock:';
}

This work adoptsCC agreement, reprint must indicate the author and the link to this article

Recommended Today

Game case | application evolution and practice of service mesh in happy games

author Chen Zhiwei, Tencent level 12 background expert engineer, is now responsible for the public background technology research and development and team management of happy game studio. Rich experience in micro service distributed architecture and game background operation and maintenance research and development. preface The background of happy game studio is a distributed micro service […]