首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

微信 Access Token 獲取與緩存策略:文件存儲 vs Memcache 實現

     編輯:PHP 綜合知識

為什麼需要緩存 Access Token

  • 微信規定 access_token 有效期 7200 秒(2 小時)。
  • 頻繁請求會觸發接口限流(每日調用上限 2000 次)。
  • 多進程/分佈式環境下需共享緩存,避免重複獲取導致舊 token 失效。

方案一:文件存儲(單機/簡單項目)

function getAccessToken() {
    $file = __DIR__ . '/access_token.json';
    $data = file_exists($file) ? json_decode(file_get_contents($file), true) : ['expire_time' => 0];

    if ($data['expire_time'] < time()) {
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}";
        $res = json_decode(file_get_contents($url), true);
        if (isset($res['access_token'])) {
            $data['access_token'] = $res['access_token'];
            $data['expire_time'] = time() + 7000; // 提前 200 秒刷新
            file_put_contents($file, json_encode($data));
        } else {
            throw new Exception('獲取失敗: ' . ($res['errmsg'] ?? 'unknown'));
        }
    }
    return $data['access_token'];
}

方案二:Memcache 存儲(分佈式/高併發)

function getAccessToken($appid, $appsecret) {
    $mem = new Memcache();
    $mem->connect('127.0.0.1', 11211);
    $key = "access_token_{$appid}";

    $token = $mem->get($key);
    if ($token) return $token;

    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
    $res = json_decode(file_get_contents($url), true);
    if (isset($res['access_token'])) {
        $mem->set($key, $res['access_token'], 0, 7000); // 過期時間 7000 秒
        return $res['access_token'];
    }
    throw new Exception('獲取失敗');
}

進階:Redis + 分佈式鎖防止緩存擊穿

function getAccessTokenRedis($appid, $appsecret) {
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $key = "wx:access_token:{$appid}";
    $lockKey = "wx:lock:access_token:{$appid}";

    $token = $redis->get($key);
    if ($token) return $token;

    // 獲取分佈式鎖
    $lock = $redis->set($lockKey, 1, ['nx', 'ex' => 10]);
    if ($lock) {
        try {
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
            $res = json_decode(file_get_contents($url), true);
            if (isset($res['access_token'])) {
                $redis->setex($key, 7000, $res['access_token']);
                return $res['access_token'];
            }
        } finally {
            $redis->del($lockKey);
        }
    } else {
        // 等待並重試
        usleep(50000);
        return getAccessTokenRedis($appid, $appsecret);
    }
}

最佳實踐總結

維度文件存儲MemcacheRedis(推薦)
適用場景單機、低併發多機、中等併發高併發、分佈式、需持久化
原子操作需自行加文件鎖不支持原子獲取並設置支持 SET NX EX / Lua 腳本
數據結構簡單 Key-Value簡單 Key-Value豐富(Hash、List、Set...)
高可用無需自建集群支持 Sentinel/Cluster

關鍵提示

  • 提前刷新:緩存過期時間設為 7000 秒(< 7200),留出網絡波動緩衝。
  • 異常重試:獲取失敗時應有指數退避重試機制,並記錄告警日誌。
  • 多公眾號隔離:Key 必須包含 appid,避免相互覆蓋。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved