# 《Seckill秒杀系统》第60章:商品库存分库分表与分桶编码实现

作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)

沉淀,成长,突破,帮助他人,成就自我。

  • 本章难度:★★★☆☆
  • 本章重点:重点理解并掌握商品库存分库分表与分桶的设计思想,掌握商品库存分库分表与分桶的核心实现逻辑,并能够将分库分表与分桶设计的核心思想与落地方案灵活运用到自身实际项目中。

大家好,我是冰河~~

在前面的章节中,我们完成了秒杀系统的微服务改造,将秒杀系统由单体应用架构升级成微服务架构,分别通过TCC模型、AT模型和可靠消息最终一致性模型解决了分布式事务问题,并且对秒杀系统的下单流程、扣减商品库存的流程进行了异步化设计和实现。秒杀系统应用层面的性能得到了极大的提升。并且,我们还在设计层面对商品的库存进行了分库分表和分桶,旨在提升商品库存在数据读写层面的性能。

# 一、前言

秒杀系统本质上就是一个高并发读和高并发写的场景,我们在不断迭代和优化秒杀系统的过程中,就是要不断的提升高并发读和高并发写的性能。对于商品库存来说,本质上既要承担高并发读流量,又要承担高并发写流量,所以,需要对商品库存进一步优化。在前面的文章中,介绍了如何对秒杀商品的库存进行分库分表和分桶设计,那么,设计了分库分表和分桶,又该如何实现呢?

# 二、本章诉求

从代码层面实现秒杀商品库存的分库分表与分桶逻辑,通过接口能够对库存的分桶数据进行实时灵活的调整,并且在实现的过程中要考虑缓存与数据库数据的一致性问题,要达到缓存层面数据的弱一致性,数据库层面数据的强一致性。

注意:由于本章的对应的源码是新增了一个seckill-stock工程,涉及到的源码细节比较多,本章只会给出实现库存分库分表和分桶逻辑最核心的源码部分,对应的源码其他细节部分,大家可以阅读本章对应的源码分支,这里不再赘述。

# 三、核心领域数据模型

对于商品库存分库分表和分桶后的数据来说,并不会像秒杀商品那样存储整个商品的信息,而是只存储与商品库存相关的数据,最核心的就是要存储每个分桶下的总库存数量和可用库存数量,另外,由于库存是针对某件商品来说的,所以,还要存储商品的id。除此之外,对于分库分表和分桶之后的库存来说,还要有一些状态的变化以及区分分桶的编号信息。

所以,梳理完这些逻辑之后,我们大致就能够定义出秒杀商品的库存在分库分表和分桶之后的核心领域数据模型对象,所以,在此基础上,我们就可以定义出商品库存的实现类SeckillStockBucket。SeckillStockBucket类的源码详见:seckill-stock-domain工程下的io.binghe.seckill.stock.domain.model.entity.SeckillStockBucket。

public class SeckillStockBucket implements Serializable {
    private static final long serialVersionUID = 6965796752002288513L;
    //数据主键id
    private Long id;
    //商品id
    private Long goodsId;
    //初始库存
    private Integer initialStock;
    //当前可用库存
    private Integer availableStock;
    //状态,0: 不可用; 1:可用
    private Integer status;
    //分桶编号
    private Integer serialNo;

    public SeckillStockBucket() {
    }

    public SeckillStockBucket(Long goodsId, Integer initialStock, Integer availableStock, Integer status, Integer serialNo) {
        this.id = SnowFlakeFactory.getSnowFlakeFromCache().nextId();
        this.goodsId = goodsId;
        this.initialStock = initialStock;
        this.availableStock = availableStock;
        this.status = status;
        this.serialNo = serialNo;
    }
    /***********省略getter/setter************/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 四、分库分表编码实现

在分库分表的实现上,我们主要通过Apache ShardingSphere实现,在分库分表的实现上,主要包含增加系统配置和创建对应的数据库和数据表。

# 4.1 增加系统配置

(1)添加项目依赖

在seckill-stock-domain工程下的pom.xml文件中添加ShardingSphere依赖,如下所示。

<properties>
    <sharding.jdbc.version>4.1.1</sharding.jdbc.version>
</properties>

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>${sharding.jdbc.version}</version>
</dependency>
1
2
3
4
5
6
7
8
9

# 查看完整文章

加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码