跳转至

特性

📌 核心特性

1. 数据结构丰富

  • String: 字符串、计数器、分布式锁
  • Hash: 对象存储、购物车
  • List: 消息队列、时间线
  • Set: 去重、共同好友
  • Sorted Set: 排行榜、延迟队列
  • Bitmap: 用户签到、状态标记
  • HyperLogLog: UV 统计
  • Geo: 地理位置计算
  • Stream: 消息队列(Kafka 轻量替代)

2. 高性能

  • 纯内存操作,读写速度 10万+ QPS
  • 单线程模型(Redis 6 前),避免上下文切换
  • IO 多路复用(epoll)

3. 持久化机制

方式 原理 优点 缺点
RDB 快照 恢复快、文件小 可能丢失数据
AOF 操作日志 数据更安全 文件大、恢复慢
混合持久化 RDB+AOF 兼顾两者 Redis 4.0+

4. 高可用架构

  • 主从复制: 读写分离
  • Sentinel(哨兵): 基于主从,哨兵-集群监控、消息通知、故障转移、配置中心,不保证数据零丟失,只能保证高可用。
  • Cluster(集群): 数据分片、水平扩展;数据分片存储在多个互为主从的多节点上,数据写入主节点,再同步到从节点,不保证强一致性。

5. 其他特性

  • 事务: MULTI/EXEC(不支持回滚)
  • 发布订阅: PUB/SUB
  • Lua 脚本: 原子操作
  • 过期策略: 惰性删除 + 定期删除
  • 内存淘汰策略: LRU/LFU 等
LRU/LFU
策略 LRU(最近最少使用) LFU(最不经常使用)
触发机制 内存达到 maxmemory 阈值时触发 内存达到 maxmemory 阈值时触发
决策依据 访问时间(看最后一次读写的时间戳) 访问频次(看一段时间内的访问计数)
淘汰对象 最久没被访问的 Key 访问频率最低的 Key(且计数会衰减)
Redis 实现 allkeys-lru / volatile-lru(基于全局链表采样) allkeys-lfu / volatile-lfu(基于对数计数器 + 衰减因子)
适用场景 热点数据随时间转移(如新闻热搜) 长期热点数据(如经典商品详情页)

📌 常用命令

连接到远程Redis服务器: ./redis-cli -h ip -p port -a password

指令 说明
keys * 查看所有的键
dbsize 键总数
exists key 检查键是否存在。存在: 1,不存在: 0
del key 删除键。删除成功: 1,删除失败: 0
type key 键的数据结构类型
rename key newkey 重命名键
set key value 设置值
get key 获取对应键的值
flushdb 清除当前数据库
flushall 清除所有数据库
info memory 查询内存使用情况
CONFIG get maxclients 查最大连接数

清除指定redis: for i in $(seq 1001 1003): do echo "flushab" | ./redis-cli -h ip -a password -p $i; done

redis-cli --stat  # 看实时流量

# 监控命令
redis-cli INFO stats        # 统计信息,关注`rejected_connections`、`expired_keys`
redis-cli INFO memory       # 内存使用
redis-cli INFO clients      # 客户端连接
redis-cli INFO replication  # 主从状态

# 设置慢查询阈值为 100ms
redis-cli config set slowlog-log-slower-than 100000
# 获取最近 10 条慢查询
redis-cli slowlog get 10

# 查找大keys
redis-cli --bigkeys

📌 关键指标

  • Latency - redis响应一个请求的时间
  • instantaneous_ops_pers_sec - 每秒处理请求数(吞吐量)
  • hitrate(calculated) - 缓存命中率

🚁 缓存穿透/击穿/雪崩

问题 原因 解决方案
穿透 查询不存在的数据 布隆过滤器前置拦截、缓存空值
击穿 热点 Key 过期 互斥锁、逻辑过期
雪崩 大量 Key 同时过期 随机过期时间、集群
布隆过滤器

一种空间效率极高的概率型数据结构,用于判断一个元素是否在一个集合中。

  • 快速判断: 可以告诉你一个元素"一定不存在"或"可能存在"
  • 空间高效: 相比哈希表、树等传统数据结构,占用空间极小
  • 有误判率: 可能将不存在的元素误判为存在(假阳性),但不会将存在的元素误判为不存在(无假阴性)

应用场景

  • 缓存穿透防护: 在数据库前加布隆过滤器,避免查询不存在的数据
  • 网页爬虫去重: 判断URL是否已爬取
  • 垃圾邮件过滤: 快速判断邮件地址是否在黑名单中
  • 分布式系统: 减少网络请求,如 HBase、Cassandra 等使用它来减少磁盘 IO

缓存击穿

指某个热点数据在缓存中过期的瞬间,大量并发请求直接穿透到数据库,可能导致数据库压力骤增甚至崩溃。

常见原因:

  1. 业务代码或数据有问题。
  2. 恶意攻击、爬虫等造成大量空命中。

解决方案:

  • 逻辑过期时间: 当数据过期时,异步更新数据而不阻塞请求。
  • 使用布隆过滤器快速判断数据是否存在,避免无效请求穿透到数据库。
  • 加互斥锁: 当缓存失效时,只允许一个线程去加载数据,其他线程等待。
  • 缓存预热: 在系统启动或低峰期预先加载热点数据到缓存。

缓存雪崩

指在某个时间段内,大量的缓存同时失效或者Redis服务宕机后恢复,导致所有请求都直接访问数据库,从而引发数据库连接或性能瓶颈,甚至宕机。

常见原因:

  1. 集中过期: 设置了相同的过期时间,导致大量缓存同时失效。
  2. Redis宕机: Redis服务异常或网络中断,导致所有缓存不可用。
  3. 缓存层故障转移失败: 如集群部署时节点宕机未及时恢复。

解决方案:

  • 错峰过期,如随机扰动设置: 在基准过期时间上叠加一个随机偏移量,比如过期时间设为 3600 + random(0, 300) 秒,避免缓存同时失效。
  • 熔断限流(服务降级),在访问数据库前加入熔断机制,当请求超过阈值时直接返回错误或默认值,防止数据库被压垮。
  • 缓存高可用架构(主从、集群)
  • 多级缓存架构(本地缓存+redis缓存)

📌 Q1: 测试人员需要关注哪些特性?

  • 缓存命中hitrate,键是否被有效命中。
  • 慢查询slowlog,需要先设置阈值。
  • bigkey,数据结构选择是否合理;包括HGETALL 大Hash、SMEMBERS 大Set,阻塞主线程的时间。
  • 内存淘汰策略,是否频繁的内存逐出
  • TTL设置是否合理,如永不过期,容易造成内存泄漏。
数据结构选择
  • 复杂的数据以 Hash 结构存储,比如渠道详情、结算规则模板等。
  • 简单的数据以 String 结构存储,比如结算开关、用户Session Token等。
  • 去重类需求利用 Set 结构。
主动续期&防雪崩
  • 分布式锁的“看门狗”续期

    业界痛点: 业务执行时间超过了锁的TTL(如30秒),导致锁自动释放,其他线程获取锁造成脏数据。

    通用做法: 不设置固定TTL,而是由后台守护线程(Watchdog)每隔一段时间(如 TTL 的 1/3)检查,若业务未完成,自动执行 EXPIRE 续期。只有在业务完成或进程挂掉时,守护线程才停止续期(Redisson 的经典实现)。

  • 滑动窗口过期(业务层实现)

    Redis 自身不支持“每次访问都自动续期”,通过在业务代码的 GET 操作后,主动调用 EXPIRE key 3600 来模拟 Session 的滑动过期机制。

    适用场景: 用户登录 Session(Token),只要用户在操作,登录态就一直延续。

    注意: 这会增加写操作开销,尤其是热点key被大量访问时,会大幅增加网络IO和CPU开销。建议采样续期(例如只续期10%的请求)。

  • 冷热数据分层TTL

    Caffeine(本地缓存) + Redis(分布式缓存),TTL错位的二级缓存。

    策略: 本地缓存 TTL 极短(如30秒),Redis 缓存 TTL 较长(如600秒)。

    意图: 本地缓存用于扛超高并发(百万级 QPS),短 TTL保证数据相对新鲜;Redis 用于跨节点共享。

    注意: 两者刚好同时过期,会导致缓存穿透。解决方案: 本地缓存提前异步刷新(在 TTL 还剩20%时主动去 Redis 拉取)。

📌 Q2: Redis 通常存储哪些类型的业务数据?存储的原因是什么?

通常存储的业务数据:

  • 高频读取的配置类数据: 比如计酬数据源、渠道的基本信息、结算规则模板、费率参数等。这些数据在结算周期内几乎不变,但查询极度频繁。
  • 状态与中间结果: 计酬计算的引擎执行时的临时变量、状态管理等。
  • 安全与权限数据: 用户的 Session Token、接口防刷的频率限制(Rate Limiting)以及各地市操作员的菜单权限缓存。

存储的原因:

  • 降低数据库压力: 减少数据库IO,同时加速读取;高并发或大批量导出时,数据库 CPU 会瞬间飙升。通过 Redis 做缓冲层,可以将响应耗时从百毫秒级降低到毫秒级。
  • 支持分布式一致性: 多实例部署时,如果数据存在本地内存,多个实例间无法同步。Redis 作为分布式缓存,保证了所有节点读取到的状态是唯一的。
  • 利用原子性操作: 在处理渠道费用发放额度时,我们利用 Redis 的原子操作来防止‘超发’或‘并发覆盖’问题,这比在关系型数据库加锁成本更低。