前言
一般来说电商的日订单都是百千万级甚至是亿万级别的了,小小的数据库肯定是撑不住的,这时候就要提前考虑分库分表了。
国内一般大厂规则参考:
- 单表500万条记录,正常水平
- 800万条警戒线
- 1000万条必须要分库分表
一般业界,对订单数据的分库分表,有两类思路:按照订单号来切分、按照用户id来切分,当然各有利弊,这里不细说。
手动分表
这个在秒杀一中已有体现,这里仅仅是分表而已,提供一种思路,供参考,测试的时候自行建表。
按照用户 ID
来做 hash
分散订单数据。为了减少迁移的数据量,一般扩容是以倍数的形式增加。比如原来是8个库,扩容的时候,就要增加到16个库,再次扩容,就增加到32个库。这样迁移的数据量,就小很多了。
这个问题不算很大问题,毕竟一次扩容,可以保证比较长的时间,而且使用倍数增加的方式,已经减少了数据迁移量。
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
:
<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
:
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
定义实体类,项目启动会自动生成表,也可以手动创建表:
@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;
}
模拟订单插入:
@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_0
和t_order_1
分别有5条记录,说明配置成功。
小结
以上仅仅是一个小小的案例,大部分猿媛都不大可能接触电商实战,实际上业务极其复杂,复杂到小编都不敢轻易在这里吹牛逼。终其一生,很多公司的数据库可能还不过百万尔尔。
推荐
一款从0到1构建分布式秒杀系统,脱离案例讲架构都是耍流氓。
码址:gitee.com/52itstyle/spring-boot-seckill