diff --git a/internal/session/fallback_store.go b/internal/session/fallback_store.go index 391e3f2..af847d6 100644 --- a/internal/session/fallback_store.go +++ b/internal/session/fallback_store.go @@ -112,19 +112,22 @@ func (fs *FallbackStore) migrateSessions() { return } - // 收集迁移涉及的用户 - userSet := make(map[uint]bool, len(sessions)) - for _, s := range sessions { - userSet[s.UserID] = true - } - ctx := context.Background() - // 先清理 Redis 中同用户的旧会话(降级期间用户重新登录,旧会话已失效) - // 避免 Redis 恢复后出现新旧两条会话并存、设备列表重复 - for uid := range userSet { - if err := fs.redis.DeleteByUID(uid); err != nil { - log.Printf("[FallbackStore] 迁移前清理旧会话失败 uid=%d err=%v", uid, err) + // 清理 Redis 中同设备的旧会话(仅针对降级期间重新登录的设备) + // 匹配规则:同一用户 + 同 UserAgent + 同 IP 的旧会话视为同设备残留,其他设备会话保留 + for _, migrated := range sessions { + oldSessions, err := fs.redis.ListByUID(migrated.UserID) + if err != nil { + log.Printf("[FallbackStore] 迁移时查找旧会话失败 uid=%d err=%v", migrated.UserID, err) + continue + } + for _, old := range oldSessions { + if old.IP == migrated.IP && old.UserAgent == migrated.UserAgent { + if delErr := fs.redis.Delete(old.ID); delErr != nil { + log.Printf("[FallbackStore] 迁移时清理同设备旧会话失败 sid=%s err=%v", old.ID[:16]+"...", delErr) + } + } } } @@ -155,7 +158,7 @@ func (fs *FallbackStore) migrateSessions() { _ = fs.memory.Delete(s.ID) } - log.Printf("[FallbackStore] Redis 已恢复,静默迁移 %d 条会话(旧会话已清理,内存已释放)", len(sessions)) + log.Printf("[FallbackStore] Redis 已恢复,静默迁移 %d 条会话(内存已释放)", len(sessions)) } // ping 检查 Redis 连接状态(带超时)