1.增加互斥锁:保证缓存和数据库数据一致性
2.增加消费队列,保证mysql数据的正常保存
This commit is contained in:
@@ -66,6 +66,45 @@ final class GameHotDataRedis
|
||||
self::redisDel(self::KEY_GC . $configKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按库中当前行覆盖 game_config 缓存(无行则删缓存)
|
||||
*/
|
||||
public static function gameConfigReplaceFromDb(string $configKey): void
|
||||
{
|
||||
if ($configKey === '' || !self::enabled()) {
|
||||
return;
|
||||
}
|
||||
$row = Db::name('game_config')->where('config_key', $configKey)->find();
|
||||
if (!$row) {
|
||||
self::gameConfigForget($configKey);
|
||||
return;
|
||||
}
|
||||
$ttl = self::intConfig('ttl_game_config', 86400);
|
||||
self::redisSetEx(self::KEY_GC . $configKey, $ttl, json_encode($row, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对局写入后:刷新指定 id 的行缓存,并删除「活跃局 / 最新局」聚合键以免脏读
|
||||
*
|
||||
* @param int|null $id 可为 null(仅清聚合键)
|
||||
*/
|
||||
public static function gameRecordSyncCachesAfterDbWrite(?int $id): void
|
||||
{
|
||||
if (!self::enabled()) {
|
||||
return;
|
||||
}
|
||||
if ($id !== null && $id > 0) {
|
||||
$row = Db::name('game_record')->where('id', $id)->find();
|
||||
if ($row) {
|
||||
$ttl = self::intConfig('ttl_game_record', 60);
|
||||
self::redisSetEx(self::KEY_GR_ID . $id, $ttl, json_encode($row, JSON_UNESCAPED_UNICODE));
|
||||
} else {
|
||||
self::redisDel(self::KEY_GR_ID . $id);
|
||||
}
|
||||
}
|
||||
self::redisDel(self::KEY_GR_ACTIVE, self::KEY_GR_LATEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
@@ -212,6 +251,49 @@ final class GameHotDataRedis
|
||||
self::redisDel(self::KEY_USER . $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据库读取最新 user 行并覆盖写入 Redis(与 DB 同事务后调用,保持缓存与库一致)
|
||||
*/
|
||||
public static function userReplaceCacheFromDb(int $userId): void
|
||||
{
|
||||
if ($userId <= 0 || !self::enabled()) {
|
||||
return;
|
||||
}
|
||||
$row = Db::name('user')->where('id', $userId)->find();
|
||||
if (!$row) {
|
||||
self::userForget($userId);
|
||||
return;
|
||||
}
|
||||
$ttl = self::intConfig('ttl_user', 90);
|
||||
self::redisSetEx(self::KEY_USER . $userId, $ttl, json_encode($row, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试获取「后台修改该用户」互斥锁(Redis SET NX EX)。
|
||||
* 与热点缓存开关无关:只要 Redis 可用即加锁;连接失败时降级为仅依赖数据库乐观锁(WHERE coin=)。
|
||||
*
|
||||
* @return array{acquired: bool, token: ?string, redis_lock: bool}
|
||||
*/
|
||||
public static function userAdminMutationLockTry(int $userId): array
|
||||
{
|
||||
if ($userId <= 0) {
|
||||
return ['acquired' => false, 'token' => null, 'redis_lock' => false];
|
||||
}
|
||||
|
||||
return GameHotDataLock::tryAcquire(GameHotDataLock::TYPE_USER, (string) $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放 userAdminMutationLockTry 取得的锁(仅当 redis_lock 且 token 非空)
|
||||
*/
|
||||
public static function userAdminMutationLockRelease(int $userId, ?string $token, bool $redisLock): void
|
||||
{
|
||||
if ($userId <= 0) {
|
||||
return;
|
||||
}
|
||||
GameHotDataLock::release(GameHotDataLock::TYPE_USER, (string) $userId, $token, $redisLock);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用缓存行构造已存在库的 User(供 Auth 等高频读)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user