单用户N天M次频控缓存设计

一. 复杂点

  1. M和N均会变化
  2. 需支持变更实时生效
  3. 对超领零容忍
  4. 可能需要溯源, 如原来5天3次改成7天2次时, 原来5天内买了1次的用户只能再领1次

二. 隐含条件

  1. 业务上N的最大值Nmax
    如一般送体验会员, 频控最大周期为一个月, Nmax可以取2个月
  2. 业务上M都比较小(这意味着缓存数据的空间几乎可以忽略不计)

三. 方案选择

方案1

  1. kv结构
  2. key为uid+resourceId,value为领取次数
  3. expire为当前周期第1次领取资格时间向后偏移当时的N天

方案2

  1. zset结构
  2. key为uid+resourceId,member为orderNo,score为领券时间
  3. expireAt为领取资格时间向后偏移潜在的最大Nmax, 每次领取(expire+惰性检查删除)
  4. 领取次数通过size来获取

方案比较

  1. 方案1的过期时间包含N, 但N变化时不好处理
  2. 每次领取资格的时间不知道, 当规则变化时没法最大程度兼容上一版本的规则, 如原来5天3次改成7天2次时, 原来领过1次的用户只能再领券1次就不好实现, 因为没有每次的领券时间戳, 不符合业务预期
  3. 方案适用的场景: N不会变化
  1. 方案2将过期时间固定取潜在最大Nmax
  2. 有领取资格时间, N变化时也可根据score精确溯源
  3. 配置变化时会最大程度兼容上一版本, 丝滑过渡

方案二的时序图:
单用户N天M次频控缓存设计


四. 拓展

  1. 上述的N为非自然月/周, 如果需要设置成每资源日/周/月重置次数, 则计算expire时还要查找最近的重置临界点
  2. 某些场景M=1, 如3天弹窗1次, 5天内不重复等诉求, 此时方案2的缓存结构可以直接简化为

zset结构, key为uid, member为resourceId,score为领券时间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值