发布于

Redis 缓存架构设计:高性能缓存系统的构建与优化

作者

Redis 缓存架构设计:高性能缓存系统的构建与优化

Redis 是一个高性能的内存数据结构存储系统,广泛用作缓存、消息队列和数据库。本文将深入探讨 Redis 的架构设计、缓存策略和性能优化。

Redis 基础架构

数据结构与应用场景

// Redis 客户端封装
const redis = require('redis')

class RedisClient {
  constructor(config = {}) {
    this.client = redis.createClient({
      host: config.host || 'localhost',
      port: config.port || 6379,
      password: config.password,
      db: config.db || 0,
      retry_strategy: (options) => {
        if (options.error && options.error.code === 'ECONNREFUSED') {
          return new Error('Redis 服务器拒绝连接')
        }
        if (options.total_retry_time > 1000 * 60 * 60) {
          return new Error('重试时间已用尽')
        }
        if (options.attempt > 10) {
          return undefined
        }
        return Math.min(options.attempt * 100, 3000)
      },
    })

    this.client.on('error', (err) => {
      console.error('Redis 连接错误:', err)
    })

    this.client.on('connect', () => {
      console.log('Redis 连接成功')
    })
  }

  // String 操作 - 简单缓存
  async setCache(key, value, ttl = 3600) {
    try {
      const serializedValue = JSON.stringify(value)
      if (ttl > 0) {
        await this.client.setex(key, ttl, serializedValue)
      } else {
        await this.client.set(key, serializedValue)
      }
      return true
    } catch (error) {
      console.error('设置缓存失败:', error)
      return false
    }
  }

  async getCache(key) {
    try {
      const value = await this.client.get(key)
      return value ? JSON.parse(value) : null
    } catch (error) {
      console.error('获取缓存失败:', error)
      return null
    }
  }

  // Hash 操作 - 对象缓存
  async setHashCache(key, field, value, ttl = 3600) {
    try {
      await this.client.hset(key, field, JSON.stringify(value))
      if (ttl > 0) {
        await this.client.expire(key, ttl)
      }
      return true
    } catch (error) {
      console.error('设置 Hash 缓存失败:', error)
      return false
    }
  }

  async getHashCache(key, field) {
    try {
      const value = await this.client.hget(key, field)
      return value ? JSON.parse(value) : null
    } catch (error) {
      console.error('获取 Hash 缓存失败:', error)
      return null
    }
  }

  async getAllHashCache(key) {
    try {
      const hash = await this.client.hgetall(key)
      const result = {}
      for (const [field, value] of Object.entries(hash)) {
        result[field] = JSON.parse(value)
      }
      return result
    } catch (error) {
      console.error('获取所有 Hash 缓存失败:', error)
      return {}
    }
  }

  // List 操作 - 队列和栈
  async pushToList(key, value, direction = 'left') {
    try {
      const serializedValue = JSON.stringify(value)
      if (direction === 'left') {
        return await this.client.lpush(key, serializedValue)
      } else {
        return await this.client.rpush(key, serializedValue)
      }
    } catch (error) {
      console.error('推入列表失败:', error)
      return 0
    }
  }

  async popFromList(key, direction = 'left') {
    try {
      let value
      if (direction === 'left') {
        value = await this.client.lpop(key)
      } else {
        value = await this.client.rpop(key)
      }
      return value ? JSON.parse(value) : null
    } catch (error) {
      console.error('弹出列表失败:', error)
      return null
    }
  }

  // Set 操作 - 去重集合
  async addToSet(key, ...values) {
    try {
      const serializedValues = values.map((v) => JSON.stringify(v))
      return await this.client.sadd(key, ...serializedValues)
    } catch (error) {
      console.error('添加到集合失败:', error)
      return 0
    }
  }

  async getSetMembers(key) {
    try {
      const members = await this.client.smembers(key)
      return members.map((m) => JSON.parse(m))
    } catch (error) {
      console.error('获取集合成员失败:', error)
      return []
    }
  }

  // Sorted Set 操作 - 排行榜
  async addToSortedSet(key, score, member) {
    try {
      const serializedMember = JSON.stringify(member)
      return await this.client.zadd(key, score, serializedMember)
    } catch (error) {
      console.error('添加到有序集合失败:', error)
      return 0
    }
  }

  async getSortedSetRange(key, start = 0, stop = -1, withScores = false) {
    try {
      let result
      if (withScores) {
        result = await this.client.zrange(key, start, stop, 'WITHSCORES')
        const parsed = []
        for (let i = 0; i < result.length; i += 2) {
          parsed.push({
            member: JSON.parse(result[i]),
            score: parseFloat(result[i + 1]),
          })
        }
        return parsed
      } else {
        result = await this.client.zrange(key, start, stop)
        return result.map((m) => JSON.parse(m))
      }
    } catch (error) {
      console.error('获取有序集合范围失败:', error)
      return []
    }
  }
}

缓存策略实现

// 缓存策略管理器
class CacheStrategyManager {
  constructor(redisClient) {
    this.redis = redisClient
    this.defaultTTL = 3600 // 1小时
  }

  // Cache-Aside 模式
  async cacheAside(key, fetchFunction, ttl = this.defaultTTL) {
    try {
      // 1. 先从缓存获取
      let data = await this.redis.getCache(key)

      if (data !== null) {
        console.log(`缓存命中: ${key}`)
        return data
      }

      // 2. 缓存未命中,从数据源获取
      console.log(`缓存未命中: ${key}`)
      data = await fetchFunction()

      // 3. 将数据写入缓存
      if (data !== null && data !== undefined) {
        await this.redis.setCache(key, data, ttl)
        console.log(`数据已缓存: ${key}`)
      }

      return data
    } catch (error) {
      console.error('Cache-Aside 策略执行失败:', error)
      // 缓存失败时直接返回数据源数据
      return await fetchFunction()
    }
  }

  // Write-Through 模式
  async writeThrough(key, data, writeFunction, ttl = this.defaultTTL) {
    try {
      // 1. 同时写入缓存和数据源
      const [cacheResult, dbResult] = await Promise.all([
        this.redis.setCache(key, data, ttl),
        writeFunction(data),
      ])

      if (!cacheResult) {
        console.warn(`缓存写入失败: ${key}`)
      }

      return dbResult
    } catch (error) {
      console.error('Write-Through 策略执行失败:', error)
      throw error
    }
  }

  // Write-Behind 模式
  async writeBehind(key, data, writeFunction, ttl = this.defaultTTL) {
    try {
      // 1. 立即写入缓存
      await this.redis.setCache(key, data, ttl)

      // 2. 异步写入数据源
      setImmediate(async () => {
        try {
          await writeFunction(data)
          console.log(`异步写入完成: ${key}`)
        } catch (error) {
          console.error(`异步写入失败: ${key}`, error)
          // 可以实现重试机制或将失败的写入加入队列
        }
      })

      return data
    } catch (error) {
      console.error('Write-Behind 策略执行失败:', error)
      throw error
    }
  }

  // 多级缓存
  async multiLevelCache(key, fetchFunction, l1TTL = 300, l2TTL = 3600) {
    const l1Key = `l1:${key}`
    const l2Key = `l2:${key}`

    try {
      // Level 1 缓存检查(短期缓存)
      let data = await this.redis.getCache(l1Key)
      if (data !== null) {
        console.log(`L1 缓存命中: ${key}`)
        return data
      }

      // Level 2 缓存检查(长期缓存)
      data = await this.redis.getCache(l2Key)
      if (data !== null) {
        console.log(`L2 缓存命中: ${key}`)
        // 将数据提升到 L1 缓存
        await this.redis.setCache(l1Key, data, l1TTL)
        return data
      }

      // 缓存未命中,从数据源获取
      console.log(`缓存完全未命中: ${key}`)
      data = await fetchFunction()

      if (data !== null && data !== undefined) {
        // 同时写入两级缓存
        await Promise.all([
          this.redis.setCache(l1Key, data, l1TTL),
          this.redis.setCache(l2Key, data, l2TTL),
        ])
      }

      return data
    } catch (error) {
      console.error('多级缓存策略执行失败:', error)
      return await fetchFunction()
    }
  }

  // 缓存预热
  async warmupCache(warmupTasks) {
    console.log('开始缓存预热...')
    const results = []

    for (const task of warmupTasks) {
      try {
        const { key, fetchFunction, ttl = this.defaultTTL } = task
        const data = await fetchFunction()

        if (data !== null && data !== undefined) {
          await this.redis.setCache(key, data, ttl)
          results.push({ key, status: 'success' })
          console.log(`预热成功: ${key}`)
        } else {
          results.push({ key, status: 'no_data' })
        }
      } catch (error) {
        console.error(`预热失败: ${task.key}`, error)
        results.push({ key: task.key, status: 'error', error: error.message })
      }
    }

    console.log('缓存预热完成')
    return results
  }
}

高级缓存模式

1. 分布式锁实现

// 分布式锁管理器
class DistributedLockManager {
  constructor(redisClient) {
    this.redis = redisClient
  }

  // 获取分布式锁
  async acquireLock(lockKey, lockValue, expireTime = 30000) {
    try {
      // 使用 SET NX EX 命令实现原子性锁获取
      const result = await this.redis.client.set(lockKey, lockValue, 'PX', expireTime, 'NX')

      return result === 'OK'
    } catch (error) {
      console.error('获取分布式锁失败:', error)
      return false
    }
  }

  // 释放分布式锁(使用 Lua 脚本确保原子性)
  async releaseLock(lockKey, lockValue) {
    const luaScript = `
      if redis.call("get", KEYS[1]) == ARGV[1] then
        return redis.call("del", KEYS[1])
      else
        return 0
      end
    `

    try {
      const result = await this.redis.client.eval(luaScript, 1, lockKey, lockValue)
      return result === 1
    } catch (error) {
      console.error('释放分布式锁失败:', error)
      return false
    }
  }

  // 带重试的锁获取
  async acquireLockWithRetry(
    lockKey,
    lockValue,
    expireTime = 30000,
    maxRetries = 10,
    retryDelay = 100
  ) {
    for (let i = 0; i < maxRetries; i++) {
      const acquired = await this.acquireLock(lockKey, lockValue, expireTime)

      if (acquired) {
        return true
      }

      if (i < maxRetries - 1) {
        await new Promise((resolve) => setTimeout(resolve, retryDelay))
      }
    }

    return false
  }

  // 自动续期锁
  async acquireLockWithRenewal(lockKey, lockValue, expireTime = 30000, renewalInterval = 10000) {
    const acquired = await this.acquireLock(lockKey, lockValue, expireTime)

    if (!acquired) {
      return null
    }

    const renewalTimer = setInterval(async () => {
      try {
        const luaScript = `
          if redis.call("get", KEYS[1]) == ARGV[1] then
            return redis.call("pexpire", KEYS[1], ARGV[2])
          else
            return 0
          end
        `

        const result = await this.redis.client.eval(luaScript, 1, lockKey, lockValue, expireTime)

        if (result === 0) {
          console.warn(`锁续期失败,锁可能已被其他进程获取: ${lockKey}`)
          clearInterval(renewalTimer)
        }
      } catch (error) {
        console.error('锁续期失败:', error)
        clearInterval(renewalTimer)
      }
    }, renewalInterval)

    return {
      release: async () => {
        clearInterval(renewalTimer)
        return await this.releaseLock(lockKey, lockValue)
      },
    }
  }
}

// 使用示例
class CacheWithLock {
  constructor(redisClient) {
    this.redis = redisClient
    this.lockManager = new DistributedLockManager(redisClient)
  }

  // 防止缓存击穿的安全缓存更新
  async safeUpdateCache(key, fetchFunction, ttl = 3600) {
    const lockKey = `lock:${key}`
    const lockValue = `${Date.now()}-${Math.random()}`

    try {
      // 先尝试从缓存获取
      let data = await this.redis.getCache(key)
      if (data !== null) {
        return data
      }

      // 获取分布式锁
      const lockAcquired = await this.lockManager.acquireLockWithRetry(
        lockKey,
        lockValue,
        30000, // 30秒过期
        5, // 最多重试5次
        200 // 重试间隔200ms
      )

      if (!lockAcquired) {
        // 获取锁失败,再次尝试从缓存获取(可能其他进程已更新)
        data = await this.redis.getCache(key)
        return data !== null ? data : await fetchFunction()
      }

      try {
        // 双重检查,防止重复计算
        data = await this.redis.getCache(key)
        if (data !== null) {
          return data
        }

        // 从数据源获取数据
        data = await fetchFunction()

        if (data !== null && data !== undefined) {
          await this.redis.setCache(key, data, ttl)
        }

        return data
      } finally {
        // 释放锁
        await this.lockManager.releaseLock(lockKey, lockValue)
      }
    } catch (error) {
      console.error('安全缓存更新失败:', error)
      return await fetchFunction()
    }
  }
}

2. 缓存雪崩防护

// 缓存雪崩防护管理器
class CacheAvalancheProtection {
  constructor(redisClient) {
    this.redis = redisClient
    this.lockManager = new DistributedLockManager(redisClient)
  }

  // 随机TTL防止同时过期
  getRandomTTL(baseTTL, variance = 0.2) {
    const randomFactor = 1 + (Math.random() - 0.5) * 2 * variance
    return Math.floor(baseTTL * randomFactor)
  }

  // 分层过期时间
  getLayeredTTL(layer, baseTTL = 3600) {
    const multipliers = {
      hot: 1, // 热点数据
      warm: 2, // 温数据
      cold: 4, // 冷数据
    }

    const multiplier = multipliers[layer] || 1
    return this.getRandomTTL(baseTTL * multiplier)
  }

  // 缓存预加载
  async preloadCache(keys, fetchFunctions, layer = 'warm') {
    const results = []

    for (let i = 0; i < keys.length; i++) {
      const key = keys[i]
      const fetchFunction = fetchFunctions[i]

      try {
        const data = await fetchFunction()
        const ttl = this.getLayeredTTL(layer)

        await this.redis.setCache(key, data, ttl)
        results.push({ key, status: 'success', ttl })
      } catch (error) {
        console.error(`预加载失败: ${key}`, error)
        results.push({ key, status: 'error', error: error.message })
      }
    }

    return results
  }

  // 熔断器模式
  async circuitBreakerCache(key, fetchFunction, options = {}) {
    const {
      ttl = 3600,
      failureThreshold = 5,
      recoveryTimeout = 60000,
      fallbackData = null,
    } = options

    const circuitKey = `circuit:${key}`
    const failureCountKey = `failures:${key}`

    try {
      // 检查熔断器状态
      const circuitState = await this.redis.getCache(circuitKey)

      if (circuitState === 'OPEN') {
        console.log(`熔断器开启,返回降级数据: ${key}`)
        return fallbackData
      }

      // 尝试从缓存获取
      let data = await this.redis.getCache(key)
      if (data !== null) {
        // 重置失败计数
        await this.redis.client.del(failureCountKey)
        return data
      }

      // 从数据源获取
      try {
        data = await fetchFunction()

        if (data !== null && data !== undefined) {
          const randomTTL = this.getRandomTTL(ttl)
          await this.redis.setCache(key, data, randomTTL)

          // 重置失败计数
          await this.redis.client.del(failureCountKey)
        }

        return data
      } catch (fetchError) {
        // 增加失败计数
        const failureCount = await this.redis.client.incr(failureCountKey)
        await this.redis.client.expire(failureCountKey, recoveryTimeout)

        if (failureCount >= failureThreshold) {
          // 开启熔断器
          await this.redis.setCache(circuitKey, 'OPEN', recoveryTimeout)
          console.log(`熔断器开启: ${key}`)
        }

        throw fetchError
      }
    } catch (error) {
      console.error('熔断器缓存执行失败:', error)
      return fallbackData
    }
  }
}

3. 缓存一致性保障

// 缓存一致性管理器
class CacheConsistencyManager {
  constructor(redisClient) {
    this.redis = redisClient
    this.subscribers = new Map()
  }

  // 发布缓存失效消息
  async invalidateCache(pattern, reason = 'update') {
    try {
      const message = {
        pattern,
        reason,
        timestamp: Date.now(),
        server: process.env.SERVER_ID || 'unknown',
      }

      await this.redis.client.publish('cache:invalidate', JSON.stringify(message))
      console.log(`发布缓存失效消息: ${pattern}`)
    } catch (error) {
      console.error('发布缓存失效消息失败:', error)
    }
  }

  // 订阅缓存失效消息
  async subscribeCacheInvalidation() {
    const subscriber = this.redis.client.duplicate()

    subscriber.on('message', async (channel, message) => {
      if (channel === 'cache:invalidate') {
        try {
          const { pattern, reason, timestamp, server } = JSON.parse(message)

          // 避免处理自己发送的消息
          if (server === (process.env.SERVER_ID || 'unknown')) {
            return
          }

          console.log(`收到缓存失效消息: ${pattern}, 原因: ${reason}`)

          // 删除匹配的缓存键
          await this.deleteByPattern(pattern)

          // 通知订阅者
          if (this.subscribers.has(pattern)) {
            const callbacks = this.subscribers.get(pattern)
            callbacks.forEach((callback) => {
              try {
                callback({ pattern, reason, timestamp })
              } catch (error) {
                console.error('缓存失效回调执行失败:', error)
              }
            })
          }
        } catch (error) {
          console.error('处理缓存失效消息失败:', error)
        }
      }
    })

    await subscriber.subscribe('cache:invalidate')
    return subscriber
  }

  // 按模式删除缓存
  async deleteByPattern(pattern) {
    try {
      const keys = await this.redis.client.keys(pattern)

      if (keys.length > 0) {
        await this.redis.client.del(...keys)
        console.log(`删除缓存键: ${keys.length}`)
      }
    } catch (error) {
      console.error('按模式删除缓存失败:', error)
    }
  }

  // 注册缓存失效监听器
  onCacheInvalidate(pattern, callback) {
    if (!this.subscribers.has(pattern)) {
      this.subscribers.set(pattern, [])
    }
    this.subscribers.get(pattern).push(callback)
  }

  // 版本化缓存
  async versionedCache(key, version, data, ttl = 3600) {
    const versionedKey = `${key}:v${version}`
    const versionKey = `${key}:version`

    try {
      // 设置版本化数据
      await this.redis.setCache(versionedKey, data, ttl)

      // 更新版本号
      await this.redis.setCache(versionKey, version, ttl)

      return true
    } catch (error) {
      console.error('设置版本化缓存失败:', error)
      return false
    }
  }

  async getVersionedCache(key) {
    try {
      // 获取当前版本号
      const version = await this.redis.getCache(`${key}:version`)

      if (version === null) {
        return null
      }

      // 获取版本化数据
      const versionedKey = `${key}:v${version}`
      return await this.redis.getCache(versionedKey)
    } catch (error) {
      console.error('获取版本化缓存失败:', error)
      return null
    }
  }
}

性能监控与优化

1. 缓存性能监控

// 缓存性能监控器
class CachePerformanceMonitor {
  constructor(redisClient) {
    this.redis = redisClient
    this.metrics = {
      hits: 0,
      misses: 0,
      errors: 0,
      totalRequests: 0,
      responseTime: [],
    }
    this.startTime = Date.now()
  }

  // 记录缓存命中
  recordHit(responseTime) {
    this.metrics.hits++
    this.metrics.totalRequests++
    this.recordResponseTime(responseTime)
  }

  // 记录缓存未命中
  recordMiss(responseTime) {
    this.metrics.misses++
    this.metrics.totalRequests++
    this.recordResponseTime(responseTime)
  }

  // 记录错误
  recordError() {
    this.metrics.errors++
    this.metrics.totalRequests++
  }

  // 记录响应时间
  recordResponseTime(time) {
    this.metrics.responseTime.push(time)

    // 只保留最近1000次的响应时间
    if (this.metrics.responseTime.length > 1000) {
      this.metrics.responseTime.shift()
    }
  }

  // 获取性能统计
  getStats() {
    const hitRate =
      this.metrics.totalRequests > 0
        ? ((this.metrics.hits / this.metrics.totalRequests) * 100).toFixed(2)
        : 0

    const avgResponseTime =
      this.metrics.responseTime.length > 0
        ? (
            this.metrics.responseTime.reduce((a, b) => a + b, 0) / this.metrics.responseTime.length
          ).toFixed(2)
        : 0

    const p95ResponseTime = this.getPercentile(this.metrics.responseTime, 0.95)
    const p99ResponseTime = this.getPercentile(this.metrics.responseTime, 0.99)

    return {
      hitRate: `${hitRate}%`,
      totalRequests: this.metrics.totalRequests,
      hits: this.metrics.hits,
      misses: this.metrics.misses,
      errors: this.metrics.errors,
      avgResponseTime: `${avgResponseTime}ms`,
      p95ResponseTime: `${p95ResponseTime}ms`,
      p99ResponseTime: `${p99ResponseTime}ms`,
      uptime: `${Math.floor((Date.now() - this.startTime) / 1000)}s`,
    }
  }

  // 计算百分位数
  getPercentile(arr, percentile) {
    if (arr.length === 0) return 0

    const sorted = [...arr].sort((a, b) => a - b)
    const index = Math.ceil(sorted.length * percentile) - 1
    return sorted[index].toFixed(2)
  }

  // 监控装饰器
  monitor(originalMethod) {
    const monitor = this

    return async function (...args) {
      const startTime = Date.now()

      try {
        const result = await originalMethod.apply(this, args)
        const responseTime = Date.now() - startTime

        if (result !== null && result !== undefined) {
          monitor.recordHit(responseTime)
        } else {
          monitor.recordMiss(responseTime)
        }

        return result
      } catch (error) {
        monitor.recordError()
        throw error
      }
    }
  }

  // Redis 性能监控
  async getRedisStats() {
    try {
      const info = await this.redis.client.info()
      const stats = {}

      info.split('\r\n').forEach((line) => {
        if (line.includes(':')) {
          const [key, value] = line.split(':')
          stats[key] = value
        }
      })

      return {
        connectedClients: stats.connected_clients,
        usedMemory: stats.used_memory_human,
        usedMemoryPeak: stats.used_memory_peak_human,
        keyspaceHits: stats.keyspace_hits,
        keyspaceMisses: stats.keyspace_misses,
        hitRate:
          stats.keyspace_hits && stats.keyspace_misses
            ? (
                (stats.keyspace_hits /
                  (parseInt(stats.keyspace_hits) + parseInt(stats.keyspace_misses))) *
                100
              ).toFixed(2) + '%'
            : '0%',
        totalCommandsProcessed: stats.total_commands_processed,
        instantaneousOpsPerSec: stats.instantaneous_ops_per_sec,
      }
    } catch (error) {
      console.error('获取 Redis 统计信息失败:', error)
      return {}
    }
  }

  // 定期报告性能
  startPerformanceReporting(interval = 60000) {
    setInterval(async () => {
      const appStats = this.getStats()
      const redisStats = await this.getRedisStats()

      console.log('=== 缓存性能报告 ===')
      console.log('应用层统计:', appStats)
      console.log('Redis 统计:', redisStats)
      console.log('==================')
    }, interval)
  }
}

2. 缓存优化建议

// 缓存优化建议器
class CacheOptimizationAdvisor {
  constructor(redisClient, monitor) {
    this.redis = redisClient
    this.monitor = monitor
  }

  // 分析缓存使用情况并给出建议
  async analyzeAndAdvise() {
    const suggestions = []

    try {
      // 1. 分析命中率
      const stats = this.monitor.getStats()
      const hitRate = parseFloat(stats.hitRate)

      if (hitRate < 80) {
        suggestions.push({
          type: 'hit_rate',
          severity: 'high',
          message: `缓存命中率较低 (${stats.hitRate}),建议检查缓存策略和TTL设置`,
        })
      }

      // 2. 分析响应时间
      const avgResponseTime = parseFloat(stats.avgResponseTime)
      if (avgResponseTime > 100) {
        suggestions.push({
          type: 'response_time',
          severity: 'medium',
          message: `平均响应时间较高 (${stats.avgResponseTime}),建议优化数据结构或网络配置`,
        })
      }

      // 3. 分析内存使用
      const redisStats = await this.monitor.getRedisStats()
      const memoryUsage = redisStats.usedMemory

      if (memoryUsage && memoryUsage.includes('G')) {
        const usage = parseFloat(memoryUsage)
        if (usage > 4) {
          suggestions.push({
            type: 'memory',
            severity: 'high',
            message: `内存使用量较高 (${memoryUsage}),建议清理过期数据或增加内存`,
          })
        }
      }

      // 4. 分析热点数据
      const hotKeys = await this.findHotKeys()
      if (hotKeys.length > 0) {
        suggestions.push({
          type: 'hot_keys',
          severity: 'medium',
          message: `发现热点数据: ${hotKeys.join(', ')},建议使用集群或读写分离`,
        })
      }

      // 5. 分析过期策略
      const expireAnalysis = await this.analyzeExpireStrategy()
      if (expireAnalysis.needsOptimization) {
        suggestions.push({
          type: 'expire_strategy',
          severity: 'low',
          message: expireAnalysis.message,
        })
      }

      return suggestions
    } catch (error) {
      console.error('缓存分析失败:', error)
      return []
    }
  }

  // 查找热点数据
  async findHotKeys() {
    try {
      // 这里简化实现,实际应该使用 Redis 的 MONITOR 命令或其他工具
      const keys = await this.redis.client.keys('*')
      const hotKeys = []

      // 模拟热点检测逻辑
      for (const key of keys.slice(0, 10)) {
        const ttl = await this.redis.client.ttl(key)
        if (ttl > 3600) {
          // TTL 大于1小时的可能是热点数据
          hotKeys.push(key)
        }
      }

      return hotKeys
    } catch (error) {
      console.error('查找热点数据失败:', error)
      return []
    }
  }

  // 分析过期策略
  async analyzeExpireStrategy() {
    try {
      const keys = await this.redis.client.keys('*')
      let withTTL = 0
      let withoutTTL = 0

      for (const key of keys) {
        const ttl = await this.redis.client.ttl(key)
        if (ttl > 0) {
          withTTL++
        } else if (ttl === -1) {
          withoutTTL++
        }
      }

      const total = withTTL + withoutTTL
      const noTTLPercentage = total > 0 ? (withoutTTL / total) * 100 : 0

      return {
        needsOptimization: noTTLPercentage > 20,
        message: `${noTTLPercentage.toFixed(1)}% 的键没有设置过期时间,建议设置合适的TTL`,
      }
    } catch (error) {
      console.error('分析过期策略失败:', error)
      return { needsOptimization: false, message: '' }
    }
  }

  // 生成优化报告
  async generateOptimizationReport() {
    const suggestions = await this.analyzeAndAdvise()
    const stats = this.monitor.getStats()
    const redisStats = await this.monitor.getRedisStats()

    return {
      timestamp: new Date().toISOString(),
      performance: {
        application: stats,
        redis: redisStats,
      },
      suggestions: suggestions,
      summary: {
        totalSuggestions: suggestions.length,
        highPriority: suggestions.filter((s) => s.severity === 'high').length,
        mediumPriority: suggestions.filter((s) => s.severity === 'medium').length,
        lowPriority: suggestions.filter((s) => s.severity === 'low').length,
      },
    }
  }
}

总结

Redis 缓存架构设计需要考虑多个方面:

  1. 数据结构选择:根据使用场景选择合适的 Redis 数据结构
  2. 缓存策略:实现 Cache-Aside、Write-Through 等缓存模式
  3. 高可用性:使用分布式锁、熔断器等保障系统稳定性
  4. 一致性保障:通过消息发布订阅维护缓存一致性
  5. 性能监控:持续监控缓存性能并进行优化

掌握这些技能,你就能构建出高性能、高可用的 Redis 缓存系统!


Redis 是现代高性能应用的核心组件,值得深入学习和实践。