redis 秒杀为什么不用incr

fiy 其他 10

回复

共3条回复 我来回复
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    Redis秒杀不使用incr的原因有以下几点:

    1. 并发竞争:使用incr命令进行秒杀时,每个请求都会对数量进行原子增加,但是在高并发情况下,多个请求同时到达时,可能会导致并发竞争,造成数量错误或者不稳定。

    2. 缓存一致性:Redis是一种基于内存的缓存数据库,数据存储在内存中,并且支持持久化到磁盘。如果使用incr命令进行秒杀,需要保证每个请求都能正常执行,如果因为网络抖动或者其他原因导致请求失败,会造成数量错误。此外,如果Redis因为故障或者重启而丢失数据,也会导致数量不一致。

    3. 数量限制:使用incr命令的方式,需要事先设置商品数量限制,如果超过限制的请求进来,会导致数量错误。而实际场景中,秒杀商品的数量通常是有限的,不适合使用incr命令进行原子增加。

    综上所述,Redis秒杀不使用incr命令主要是为了避免并发竞争、保证缓存一致性和合理控制商品数量。为了实现秒杀功能,通常会使用其他方法,例如预减库存、异步处理等。这些方法可以更好地处理高并发场景,确保秒杀的正确性和稳定性。

    1年前 0条评论
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    Redis 秒杀场景中为什么不使用 INCR 命令呢?

    1. 并发问题:INCR 命令是原子性的,但在秒杀场景中,可能会有大量的并发请求同时执行 INCR 命令,导致竞争条件。多个请求同时执行 INCR 命令会导致结果的不确定性,因此无法保证每个请求都能正确地递增计数。

    2. 初次参与者问题:INCR 命令只能递增计数,无法判断用户是否是初次参与,也无法区分重复参与。在秒杀场景中,需要考虑每个用户是否已经参与过秒杀,以避免同一用户重复秒杀商品。

    3. 没有限制数量:使用 INCR 命令进行计数无法限制参与秒杀的数量。在秒杀场景中,一般需要限制每个商品的数量,以防止商品被秒杀完毕后还有用户继续参与秒杀。

    4. 存在恶意访问风险:使用 INCR 命令进行计数需要客户端发送请求到 Redis 服务器,这可能导致恶意访问者利用脚本或工具来进行大量的请求,以达到攻击的目的。

    5. 数据存储问题:INCR 命令将计数值存在 Redis 的字符串类型中,这样的存储方式可能不够灵活。在秒杀场景中,可能需要记录更多的信息,如用户信息、秒杀时间等,使用 INCR 命令无法满足这种需求。

    综上所述,尽管 INCR 命令具有原子性,但在秒杀场景中并不适用。为了应对并发问题、初次参与者问题、数量限制、恶意访问风险和数据存储问题,需要采用其他更细粒度的方案来实现秒杀功能,如使用事务、使用 Lua 脚本、使用分布式锁等。这些方案可以更好地解决并发问题、保护数据的完整性,并提供更多的灵活性和可扩展性。

    1年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    Redis 是一款基于内存的高性能key-value存储系统,广泛应用于缓存、消息队列、实时排行榜等场景。在秒杀场景下,通常要求高并发的读写操作,Redis提供了多种适合秒杀的方法,其中常用的是使用Lua脚本结合INCR操作。

    为什么不直接使用INCR操作呢?下面通过方法、操作流程等方面来解答这个问题。

    1. INCR操作介绍

    INCR是Redis提供的一个原子操作,用于对指定的key执行自增操作。其具体流程如下:

    1. Redis首先检查key是否存在,如果不存在则新建一个key并将其值设为0。
    2. Redis将对应key的值加1,并返回增加后的值。

    2. INCR在秒杀场景下的问题

    尽管INCR操作非常方便,但在高并发的秒杀场景下,直接使用INCR存在一些问题:

    2.1 系统可用性问题

    当并发请求较多时,由于每个请求都需要执行两次网络IO(一次用于获取当前值,一次用于更新值),会导致性能问题和系统瓶颈,特别是在秒杀窗口时间很短的情况下。

    2.2 无法保证原子性

    如果没有采用额外的措施,多个请求并发执行INCR操作可能会导致竞态条件,最终导致数据不一致的问题。如两个请求同时读取到相同的值并增加后,再写回时就会发生覆盖。

    2.3 超卖问题

    使用INCR操作会导致并发请求直接将库存减为0,无法判断是否已经超卖。在秒杀场景下,必须保证库存数量准确且不被超卖。

    为了解决上述问题,可以结合Lua脚本使用INCR操作。

    3. 使用Lua脚本结合INCR操作

    Lua是一种轻量级脚本语言,Redis支持执行Lua脚本。通过使用Lua脚本可以将多条Redis命令原子性地执行,确保整个操作的原子性。

    结合Lua脚本使用INCR操作可以解决上述问题,具体流程如下:

    3.1 减库存

    通过INCR操作可以在Redis中存储库存数量,每次秒杀成功,库存减1,如果库存已经为0,说明已经售罄,秒杀失败。代码如下:

    local stock = redis.call("incr", "stock_key")
    if stock <= 0 then
        return 0 -- 返回失败标识
    else
        return 1 -- 返回成功标识
    end
    

    3.2 防止超卖

    为了防止超卖现象,可以在进行INCR操作之前先判断库存是否大于0,如果不大于0,则返回失败。

    local stock = redis.call("get", "stock_key")
    if stock <= 0 then
        return 0 -- 返回失败标识
    else
        redis.call("decr", "stock_key") -- 减库存
        return 1 -- 返回成功标识
    end
    

    3.3 原子性操作

    通过将多个Redis命令封装在Lua脚本中,可以确保这些命令的执行是原子性的,避免了竞态条件的问题。

    4. 总结

    尽管INCR操作非常方便,但在高并发的秒杀场景下直接使用INCR存在可用性和原子性的问题。为了解决这些问题,可以结合Lua脚本使用INCR操作,通过加锁、检查库存并减库存等措施,保证秒杀操作的准确性和并发安全性。这种方式不仅解决了性能问题和数据一致性问题,还能有效防止超卖现象的发生。

    1年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部