From 94ff09575469eb43fe51c0ec545ea04f2ff4b6b8 Mon Sep 17 00:00:00 2001 From: Dave King Date: Thu, 27 Nov 2025 10:06:09 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DRedis=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E8=A1=A8=E7=AB=9E=E6=80=81=E6=9D=A1=E4=BB=B6=E5=AF=BC?= =?UTF-8?q?=E8=87=B4API=20Key=E4=B8=B4=E6=97=B6=E5=A4=B1=E6=95=88=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:编辑API Key后立即使用时会偶现(概率1%)报"API密钥已过期"错误, 一会儿后自动恢复。这是因为updateApiKey()方法未传递hashedKey参数给 setApiKey(),导致映射表未更新而主数据已更新的不一致状态。 修复: - updateApiKey()传递keyData.apiKey(hashedKey)给setApiKey() - 确保每次更新API Key时映射表也被同步更新 - 添加日志记录帮助监控映射表问题 细节: 1. updateApiKey(): 传递hashedKey参数确保映射表一致性 2. validateApiKey(): 添加警告日志检测映射表缺失 3. updateApiKey(): 增强日志记录"hashMap updated" 这解决了Redis双重存储(apikey:{id}和apikey:hash_map)的 竞态条件问题。 Fix: #API-Key-Expiry-Race-Condition --- src/services/apiKeyService.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/services/apiKeyService.js b/src/services/apiKeyService.js index 105fe863..affd03a1 100644 --- a/src/services/apiKeyService.js +++ b/src/services/apiKeyService.js @@ -212,6 +212,8 @@ class ApiKeyService { const keyData = await redis.findApiKeyByHash(hashedKey) if (!keyData) { + // ⚠️ 警告:映射表查找失败,可能是竞态条件或映射表损坏 + logger.warn(`⚠️ API key not found in hash map: ${hashedKey.substring(0, 16)}... (possible race condition or corrupted hash map)`) return { valid: false, error: 'API key not found' } } @@ -714,10 +716,11 @@ class ApiKeyService { updatedData.updatedAt = new Date().toISOString() - // 更新时不需要重新建立哈希映射,因为API Key本身没有变化 - await redis.setApiKey(keyId, updatedData) + // 传递hashedKey以确保映射表一致性 + // keyData.apiKey 存储的就是 hashedKey(见generateApiKey第123行) + await redis.setApiKey(keyId, updatedData, keyData.apiKey) - logger.success(`📝 Updated API key: ${keyId}`) + logger.success(`📝 Updated API key: ${keyId}, hashMap updated`) return { success: true } } catch (error) {