问个 Redis 的问题

2021-02-26 15:51:51 +08:00
 myd

需求:

记录商品的购买用户和数量,实现:

方案一

使用哈希:

hset product_{product}  {user}  {qty}

优点:清空限制很方便,del product_{product}
缺点:hash 貌似不能针对指定 field(用户)设置缓存过期时间, 相关讨论: https://github.com/redis/redis/issues/1042 。只能在 qty 加一个过期时间 /购买,维护起来麻烦,也不太优雅。

方案二

使用字符串:

set product_{product}_{user}  {qty}

优点:可以针对产品 /用户设置过期时间,实现购买限制简单。
缺点:清空指定产品的购买限制复杂度是 O(N),类似于 keys product_{product}_* |xargs redis-cli DEL

有没有比较优雅的实现方式?

3947 次点击
所在节点    Redis
31 条回复
hw93
2021-02-26 17:27:40 +08:00
方案二再维护一个 `set product_{product} [user1, user2]`方便去`删除指定产品的全部用户的购买记录`
also24
2021-02-26 17:33:24 +08:00
@beryl #17
当你再下第三个订单的时候,keys product_{product}_{user}_* 就变成 2 了,
此时你再想下第四个订单,就需要等第二个订单超过 24 小时。
adamwong
2021-02-26 17:47:48 +08:00
每个用户存两个时间戳不就完了?代码里做判断
参考 golang 的令牌桶算法 time/rate.Limiter
yuankui
2021-02-26 17:58:32 +08:00
删除的动作不频繁就 2 方案了
PiersSoCool
2021-02-26 18:03:12 +08:00
这就是个限流器的问题 可参考开源方案
whileFalse
2021-02-26 18:29:39 +08:00
为产品指定版本号,product-{product}.{product.v}-{user}
清空产品时不做清空操作,而是产品版本号+1
palmers
2021-02-26 20:08:37 +08:00
第一次插入的时候设置 key 的过期时间 第二使用 incr 不会清理过期时间, 通过 key 获取值如果没有了一定是可以购买的 否则累加一
palmers
2021-02-26 20:09:59 +08:00
哦 可以购买的时候 还有判断 2
night98
2021-02-26 20:57:09 +08:00
redisson,有个分布式对象你可以参考下
rocky114
2021-02-26 21:31:45 +08:00
存储俩份 hset product_{product} {user} {qty},set product_{product} expire_time
lldld
2021-02-26 22:42:24 +08:00
如果“清空并重新计算指定产品的购买限制” 是实际需求, 而"删除指定产品的全部用户的购买记录"只是你想的实现方法的话, 我觉得没必要删除购买记录 key.

新增一个 key "product_reset_<product_id>", value 存重置的时间. service 这边可以定时更新(比如每 5 分钟)这个数据存在内存里面, 因为这个行为应该是运营有计划的, 所以可以要求(或者告之)他们至少要提前 10 分钟在系统设置重置.

用户购买记录, key "product_buy_<product_id>_<user_id>", value 存 购买时间,数量, ... , 购买时间,数量, 每次购买刷新过期时间为 24 小时


用户购买时, 读其购买记录, 并过滤时间早于重置时间的数量, 然后计算是否可以购买, 能购买几个

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/756528

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX