携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情
概述
前面对订单平台的业务场景进行了说明,分析了当业务数据大到一定程度的时候对系统效率 带来的影响以及不同的优化方案,在具体的方案中都有相应落地代码。
不管是在实际的业务开发中还是案例的学习中,需要尽量模拟生产环境的场景降低系统运行 的时候测试环境与生产环境的差异。
首先需要解决的就是生产真实数据量的问题。如果是已经运行一段时间的系统,生产上有比较 多的数据,可以对生产数据进行脱敏后导入到测试环境中;如果没有生产数据就需要手动创建 大批量数据。可以通过代码生成、常见的API工具批量调用接口、SQL脚本等方式生成测试数据。 本项目通过代码生成测试数据,对数据生成工具做一个简单的介绍和说明。
设计思路
- 定义一个数据批量插入工具类,进行数据插入
- 定义一个任务调用数据批量插入工具类
- 多线程调用数据插入任务
关键类说明
- InsertDataUtils: 批量插入数据工具类。
- 管理数据库连接信息,并创建数据库连接
- 拼接插入数据的SQL语句,生成PreparedStatement对象
- 循环给预编译SQL设置参数并执行
- Worker: 实现Runnable接口,循环调用InsertDataUtils插入数据
- BatchInsert: 批量插入数据客户端,循环创建多个线程并执行Worker任务插入数据
落地代码
客户端没执行一次插入的数据量为: 总数据量 = BatchInsert的线程循环次数 * Worker的循环次数 * InsertDataUtils的循环次数
public class BatchInsert {
public static void main(String[] args) {
int threadCount = 100;
int total = 100000;
int every = total / threadCount;
final CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
new Thread(new Worker(latch, i * every, (i + 1) * every)).start();
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Worker implements Runnable {
int start = 0;
int end = 0;
CountDownLatch latch;
public Worker(CountDownLatch latch, int start, int end) {
this.start = start;
this.end = end;
this.latch = latch;
}
@Override
public void run() {
for (int i = start; i < end; i++) {
InsertDataUtils insertDateUtils1 = new InsertDataUtils();
insertDateUtils1.insertBigData3();
}
latch.countDown();
}
}
public class InsertDataUtils {
//起始id
private long begin = 1;
//每次循环插入的数据量
private long end = begin+30;
private String url = "jdbc:mysql://xx.xx.xx.xx:3306/monomer_order?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT";
private String user = "root";
private String password = "xxxx";
//订单状态
private Integer[] orderStatus = {10,20,30,40,50,55,60,70};
//订单状态
private Integer[] payStatus = {1,2,3};
//配送状态
private Integer[] deliveryStatus = {0,1,2,3};
public void insertBigData3() {
//定义连接、statement对象
Connection conn ;
PreparedStatement pstm ;
PreparedStatement pstm2 ;
PreparedStatement pstm3 ;
PreparedStatement pstm4 ;
PreparedStatement pstm5 ;
try {
//加载jdbc驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//连接mysql
conn = DriverManager.getConnection(url, user, password);
//将自动提交关闭
conn.setAutoCommit(false);
//编写sql
String sql = "INSERT INTO `order_info` ( `order_no`, `order_amount`, `merchant_id`, `user_id`,`address_id`,`order_status`,pay_status,delivery_status,trans_time,recharge_time,update_time) VALUES (?,?,?,?,?,?,?,?,?,?,?);";
String sql2 ="INSERT INTO `order_item_detail` (`order_no`, `product_id`, `category_id`) VALUES (?,?,?)";
String sql3 ="INSERT INTO `order_item_detail` (`order_no`, `product_id`, `category_id`) VALUES (?,?,?)";
String sql4 ="INSERT INTO `order_item_detail` (`order_no`, `product_id`, `category_id`) VALUES (?,?,?)";
String sql5 ="INSERT INTO `order_item_detail` (`order_no`, `product_id`, `category_id`) VALUES (?,?,?)";
//预编译sql
pstm = conn.prepareStatement(sql);
pstm2 = conn.prepareStatement(sql2);
pstm3 = conn.prepareStatement(sql3);
pstm4 = conn.prepareStatement(sql4);
pstm5 = conn.prepareStatement(sql5);
Long merId = CommonUtils.createNo(1000000000);
for(int i=0;i<10;i++) {
Long userId = CommonUtils.createNo(100000000);;
//开始循环
while (begin < end) {
Long no = CommonUtils.createNo(1000000000);
String orderCode = GenerateOrderNoUtils.getOrderNo(no,merId);
Long productId = CommonUtils.createNo(100000);
//赋值
pstm.setString(1, orderCode);
pstm.setBigDecimal(2, new BigDecimal(productId));
pstm.setLong(3, merId);
pstm.setLong(4, userId);
pstm.setLong(5, 2L);
pstm.setLong(6, CommonUtils.getStatus(Arrays.asList(orderStatus)));
pstm.setLong(7, CommonUtils.getStatus(Arrays.asList(payStatus)));
pstm.setLong(8, CommonUtils.getStatus(Arrays.asList(deliveryStatus)));
pstm.setDate(9, CommonUtils.getDate());
pstm.setDate(10, CommonUtils.getDate());
pstm.setDate(11, CommonUtils.getDate());
//执行sql
pstm.execute();
pstm2.setString(1, orderCode);
pstm2.setLong(2, productId);
pstm2.setLong(3, productId);
pstm2.execute();
pstm3.setString(1, orderCode);
pstm3.setLong(2, productId);
pstm3.setLong(3, productId);
pstm3.execute();
pstm4.setString(1, orderCode);
pstm4.setLong(2, productId);
pstm4.setLong(3, productId);
pstm4.execute();
pstm5.setString(1, orderCode);
pstm5.setLong(2, productId);
pstm5.setLong(3, productId);
pstm5.execute();
begin++;
}
//执行批处理
pstm.executeBatch();
//执行批处理
pstm2.executeBatch();
//执行批处理
pstm3.executeBatch();
//执行批处理
pstm4.executeBatch();
//执行批处理
pstm5.executeBatch();
//提交事务
conn.commit();
//边界值
end += 30;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
}