聊聊如何实现一个秒杀系统

120 阅读2分钟

从零开始打造简易秒杀系统

  1. 理论分析
  2. 代码实现
  3. 压测验证

代码库

1. 防止超卖

使用数据库乐观锁的方式解决超卖问题,作者代码实现,并使用JMeter压测

乐观锁 VS 悲观锁

乐观锁: 适合数据修改较少,读取较频繁的场景。(即使出现了少量的冲突,可以省去在量的锁的开销,能提高系统吞吐量) 悲观锁: 适合写数据比较多的情况,(由于经常发生冲突,上层应用不断的retry,反而会降低性能)

2. 令牌桶限流 + 再谈超卖

使用Guava的RateLimiter实现令牌桶限流:

  1. 阻塞式: 如果桶内没有足够令牌,阻塞,直到令牌发放
  2. 非阻塞式: 如果桶内没有足够令牌,尝试等待设置好的时间,如果超过了时间还不能拿到,直接返回失败。等待时间设置为0,则等于阻塞式获取令牌。

两种算法的比较

  1. 令牌桶算法 能够限制数据平均传输速率,并且允许某种程度的突发流量

  2. 漏桶算法 能够强行限制数据的传输速率,多用于流量整型

Spring事务传播

3. 抢购接口隐藏 + 单用户限制频率

接口隐藏与单位用户限制频率

获取验证值,携带验证值下单 代码实现

4. 缓存与数据库双写问题的争议

缓存一致性问题产生的原因分析以及改进方案

  • 删除缓存,更新数据库

  • 延时双删(写数据库前删除一次缓存,写数据库后再删除一次缓存)

在删除缓存,更新数库之上做的改进,删除缓存,更新数据库,停顿一段时间,再删除缓存

  • 更新数据库,删除缓存

5. 阿里开源MySQL中间件Canal快速入门

使用Canel更新缓存

bin log 开启,日志格式设置为row MySQL的数据

  • 同步,返回slave都写成功
  • 异步,写入bin log,就算成功
  • 半同步,只有一个slave收到relay log,并且回复

6. 如何优雅的实现订单异步处理

使用RabbitMQ 异步处理代码实现

秒杀系统

逻辑清晰,代码清晰,提供了不同的问题角度,开阔一下视野

miaosha: 秒杀系统

1. RedisLimitRateWithLUA.java 使用Redis做分布式限流

public static boolean accquire() throws IOException, URISyntaxException {
        Jedis jedis = new Jedis("39.107.245.253");

        String lua =
                "local key = KEYS[1] " +
                        " local limit = tonumber(ARGV[1]) " +
                        " local current = tonumber(redis.call('get', key) or '0')" +
                        " if current + 1 > limit " +
                        " then  return 0 " +
                        " else " +
                        " redis.call('INCRBY', key,'1')" +
                        " redis.call('expire', key,'2') " +
                        " end return 1 ";

        String key = "ip:" + System.currentTimeMillis() / 1000; // 当前秒
        String limit = "3"; // 最大限制
        List<String> keys = new ArrayList<String>();
        keys.add(key);
        List<String> args = new ArrayList<String>();
        args.add(limit);
        jedis.auth("youxin11");
        String luaScript = jedis.scriptLoad(lua);
        Long result = (Long) jedis.evalsha(luaScript, keys, args);
        return result == 1;
    }

2. 分布式锁的三种实现方式

  1. 数据库
  2. redis
  3. zookeeper (临时顺序节点)

3. 其它常见问题