Redis防撞库需三重维度计数(IP、用户、IP+用户)并绑定过期时间,登录后通过session:risk_level联动风控,用Lua脚本原子化incr防并发漏判,Session分层存储避免瓶颈。

Redis计数器怎么防撞库:别只 incr 了事
单纯用 INCR 统计登录失败次数,根本挡不住黑产——他们换 IP、换账号、绕过限流,甚至故意触发错误响应来探测接口。真正有效的计数必须绑定「攻击指纹」,且和 Session 校验逻辑联动。
推荐做法是组合三重维度计数:ip:login:fail(单 IP 分钟级)、user:login:fail(单账号小时级)、ip:user:login:fail(精准碰撞指纹)。每条 key 都设 EXPIRE,比如 60 秒或 3600 秒,避免数据滞留。
- 不要只存一个全局计数器,黑产会用代理池轮询,单 IP 限制形同虚设
- 用户维度计数必须基于脱敏后的账号(如
sha256("user123@xxx.com")),防止日志泄露明文账号 - 如果用了 Redis Cluster,确保所有 key 的 hash tag 一致(如
{ip:user}:192.168.1.1:user123),避免跨 slot 请求失败
Session穿透和撞库怎么串起来防:关键在登录后校验点
撞库成功 ≠ 登录成功。很多系统在密码校验通过后就直接生成 Session 并返回 token,这是最大漏洞——黑产只要爆破出任意一个有效账号密码对,就能拿到合法 session_id,后续所有请求都绕过撞库防护。
必须把 Redis 计数器的判断延伸到 Session 创建之后:每次请求携带 session_id 时,先查该 session 对应的用户是否处于「近期高频撞库嫌疑状态」,再决定是否放行业务逻辑。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 登录成功后,往 Redis 写一条
session:{sid}:risk_level,初始值为 0;若该用户刚被撞库命中过(比如user:login:fail≥ 5),则设为 1 或更高 - 后续每个敏感接口(如充值、换绑、查余额)前,检查
GET session:{sid}:risk_level,值 > 0 就强制走二次验证或拒绝 - 注意:这个
session:{sid}:risk_level要和 Session 主体共生命周期,不能靠客户端传,必须服务端从 Redis 查
为什么用 INCRBY 而不是 INCR:避免并发漏判
高并发下多个请求几乎同时到达,只用 INCR 可能导致计数跳变(比如两个请求都读到 4,各自 +1 后写入 5,实际应为 6)。这不是理论问题,是真实压测中反复复现的漏防点。
INCRBY key 1 是原子操作,但更稳妥的是直接用 EVAL 脚本封装「读-判-增-设过期」四步,彻底规避竞态:
redis-cli --eval /dev/stdin ip:login:fail <<EOF
if redis.call("EXISTS", KEYS[1]) == 0 then
redis.call("SET", KEYS[1], 1, "EX", 60)
return 1
else
return redis.call("INCR", KEYS[1])
end
EOF
- 脚本里用
EXISTS+SET ... EX替代SETNX,因为后者不支持过期时间,得额外EXPIRE,非原子 - 别图省事用客户端做 if-else 判断,网络延迟 + 多实例部署会让条件竞争更严重
- 这个脚本要预热加载(
SCRIPT LOAD),避免每次执行都解析 Lua
防穿透策略里最容易被忽略的细节:Session 存储本身不能成为瓶颈
当 Redis 计数器开始拦截大量请求,Session 查询压力会同步上升。如果 Session 数据全存在 Redis,又没做分片或读写分离,GET session:{sid} 就可能成为新的单点瓶颈,反而放大穿透风险。
建议把 Session 拆成两层:高频读的元信息(用户 ID、角色、登录时间)放 Redis;低频读的敏感字段(如设备指纹、风控等级)放本地缓存或 DB,按需懒加载。
- 不要让每次请求都
HGETALL session:{sid},只取必要字段,用HMGET session:{sid} user_id role login_time risk_level - 如果用了 JWT 做无状态 Session,
risk_level这类动态字段就不能塞进 token,必须回查 Redis,否则无法实时降权 - 所有 Redis 调用必须设超时(建议 ≤ 100ms)和熔断(如 Hystrix 或 Sentinel),防止 Redis 慢查询拖垮整个登录链路

















