SET适用于黑白名单因其天然去重、O(1)查询、支持原子操作且服务端直接判断成员;而LIST查询为O(n),HASH冗余存value;关键需统一key/value类型(全字符串或全数字),规范key命名(如perm:whitelist:user_id:prod),并采用增量同步或双写切换保障更新无感。

为什么用 SET 而不是 HASH 或 LIST 存黑白名单
因为 SET 天然去重、查询快(O(1))、支持原子操作,且 Redis 服务端能直接完成成员判断——不用把全量数据拉到应用层再遍历。而 LIST 查找是 O(n),HASH 虽然也快,但浪费空间存冗余 value(黑白名单只关心“在不在”,不需要额外字段)。更关键的是:SISMEMBER 命令本身不阻塞、不返回全集,高并发校验时 CPU 和网络开销最小。
sismember 是核心,但 key 和 value 类型必须严格一致
常见翻车点:数据库里存的是 user_id(Long),Redis 里用 sadd whitelist "123" 存字符串,结果代码里调 isMember("whitelist", 123L) → 永远返回 false。Redis 的 SET 是按字节比较的,"123" 和 123 完全不同。
- 统一用字符串:所有写入和查询都走
String.valueOf(id)或直接传字符串 - 统一用数字:确保
sadd时用整数(如sadd whitelist 123 456),Java 侧用Long或Integer传参 - 避免混用:Spring Boot 中
RedisTemplate<string string></string>和RedisTemplate<string long></string>不能共用同一个 key
key 设计要带业务域和环境标识,别裸用 whitelist
线上出过事故:测试环境脚本误删了生产 whitelist,因为两边 key 完全一样。硬编码 "whitelist" 看似省事,实则埋雷。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 推荐格式:
perm:whitelist:user_id:prod、perm:blacklist:ip:staging - 用冒号分隔层级,语义清晰,也方便
KEYS perm:whitelist*批量排查(但线上禁用KEYS,改用SCAN) - Spring Boot 中建议抽成配置项,比如
redis.key.whitelist=user:${spring.profiles.active}
动态更新时别直接 DEL 再 SADD 全量
如果白名单有 50 万用户,一次 DEL + SADD 会卡住 Redis 主线程,期间所有请求延迟飙升。真实系统里更新必须无感。
- 增量同步:监听 MySQL binlog 或业务事件,单条
SADD/SREM - 双写+原子切换:先写新 key(如
whitelist:v2),全量导入完成后,用RENAME原子替换旧 key - 慎用
SDIFFSTORE做灰度:比如把旧白名单和待剔除列表求差,生成临时 key,验证后再切换
真正难的不是命令怎么写,而是让黑白名单在不停机、不抖动、不误判的前提下,跟上业务变化节奏——这要求你把 key 生命周期、数据一致性、failover 策略全想清楚,而不是只盯着 sismember 返回 true 还是 false。

















