分布式秒杀实战之订单数据分表

2020-08-31 10:13:46 浏览数 (1)

前言

一般来说电商的日订单都是百千万级甚至是亿万级别的了,小小的数据库肯定是撑不住的,这时候就要提前考虑分库分表了。

国内一般大厂规则参考:

  • 单表500万条记录,正常水平
  • 800万条警戒线
  • 1000万条必须要分库分表

一般业界,对订单数据的分库分表,有两类思路:按照订单号来切分、按照用户id来切分,当然各有利弊,这里不细说。

手动分表

这个在秒杀一中已有体现,这里仅仅是分表而已,提供一种思路,供参考,测试的时候自行建表。

按照用户 ID 来做 hash 分散订单数据。为了减少迁移的数据量,一般扩容是以倍数的形式增加。比如原来是8个库,扩容的时候,就要增加到16个库,再次扩容,就增加到32个库。这样迁移的数据量,就小很多了。

这个问题不算很大问题,毕竟一次扩容,可以保证比较长的时间,而且使用倍数增加的方式,已经减少了数据迁移量。

代码语言:javascript复制
String table = "success_killed_" userId%8;
nativeSql = "INSERT INTO " table " (seckill_id, user_id,state,create_time)VALUES(?,?,?,?)";
Object[] params = new Object[]{seckillId,userId,(short)0,new Timestamp(System.currentTimeMillis())};
dynamicQuery.nativeExecuteUpdate(nativeSql,params);

手动撕业务逻辑是不是很low?今天给大家推荐一款分表神器。

自动分表

墙裂推荐使用开源的分布式数据库中间件 ShardingSphere,资料丰富,入手简单, 并且已于2020年4月16日成为 Apache 软件基金会的顶级项目,值得信赖。

适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。

  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  • 支持任意实现JDBC规范的数据库。目前支持 MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。

集成 SpringBoot

案例使用 SpringBoot2.2.6.RELEASE JPA,部分坐标请自行引入。

引入坐标pom.xml

代码语言:javascript复制
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-namespace</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.23</version>
</dependency>

配置文件 application.properties

代码语言:javascript复制
server.port=8080
spring.jpa.database=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

spring.shardingsphere.datasource.names=ds
spring.shardingsphere.datasource.ds.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds.url=jdbc:mysql://localhost:3306/shardingsphere?serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.ds.username=root
spring.shardingsphere.datasource.ds.password=root
spring.shardingsphere.datasource.ds.max-active=16

spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds.t_order_$->{0..1}
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}
#自增列名称,缺省表示不使用自增主键生成器
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
#自增列值生成器类型,缺省表示使用默认自增列值生成器。可使用用户自定义的列值生成器或选择内置类型:SNOWFLAKE/UUID
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
#工作机器唯一id,默认为0,最大1024
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=6

定义实体类,项目启动会自动生成表,也可以手动创建表:

代码语言:javascript复制
@Data
@Entity
@Table(name = "t_order")
public final class OrderEntity{

    private static final long serialVersionUID = 4743102234543827854L;

    /**
     * 订单ID
     */
    @Id
    @Column(name = "order_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long orderId;

    /**
     * 商品ID
     */
    @Column(name = "goods_id")
    private long goodsId;

    /**
     * 用户ID
     */
    @Column(name = "user_id")
    private int userId;

    /**
     * 支付状态 1 支付完成 0 支付中
     */
    @Column(name = "pay_status")
    private short payStatus;

}

模拟订单插入:

代码语言:javascript复制
@Api(tags ="订单管理")
@RestController
@RequestMapping("/order")
public class OrderControl {

    @Autowired
    private OrderRepository orderRepository;

    /**
     * 插入
     */
    @PostMapping("/save")
    public void save(){
        for(int i=0;i<10;i  ){
            OrderEntity entity = new OrderEntity();
            entity.setUserId(i);
            entity.setGoodsId(1000L);
            entity.setPayStatus((short)0);
            orderRepository.save(entity);
        }
    }
}

模拟订单插入,执行请求,向数据库插入十条订单,查看数据库,如果表t_order_0t_order_1分别有5条记录,说明配置成功。

小结

以上仅仅是一个小小的案例,大部分猿媛都不大可能接触电商实战,实际上业务极其复杂,复杂到小编都不敢轻易在这里吹牛逼。终其一生,很多公司的数据库可能还不过百万尔尔。

推荐

一款从0到1构建分布式秒杀系统,脱离案例讲架构都是耍流氓。

码址:gitee.com/52itstyle/spring-boot-seckill

0 人点赞