订单系统几个特点:
1、历史信息多(每一条订单完成后,生成一条历史信息,并且一般情况下,久远的订单信息不回被经常查看)
2、并发量高(特别是秒杀系统生成的订单,每秒会有成百上千条订单)
3、订单id必须全局唯一
一、分库分表
随着订单量的增加,数据库发展如下:
已知Mysql单表性能超过千万级别会严重下降,按照千万级别来计算,假设订单系统分为16个库,每个库64个表进行存储,共1024个表,那么,Mysql最高可以存储百亿级别的订单。随着储存问题的解决,复杂度也会随之增加,例如一下问题:
下面依次解决上面的问题:
1、生成全局唯一的订单编号
这里采用了:机器ID+时间戳+自增序列(+userid后两位);
这里的机器id是因为集群部署的时候,不同机器上的订单系统的机器id是不一样的,生成的订单id也就不一样了。
时间戳可以精确到毫秒,但是如果每毫秒任然有并发,单纯使用时间戳并不能完全生成唯一订单id
自增序列每个表自己的自增序列,保证单表的订单id唯一
userid后两位,给订单id赋予一定含义。
详情可见:分布式系统唯一ID生成方案汇总
2、查询复杂度的降低-----mycat数据库中间件
中间价可以使用阿里的mycat连接,具体使用查看mycat文档。优点:代码实现简单,跟分库前差不多。
而直接使用jdbc链接,需要自己计算哪条订单存入哪个库,优点是:直接链接数据库性能更好,缺点是代码复杂度高。
3、买家卖家订单设计
由于买家与卖家有不同的查询特性,买家(用户)只会查询自己的订单,而卖家(商家)会查询自己店铺的订单,还有管理者,他可以查询所有的订单并且统计。
订单的查询特性是:一般三个月之前的订单是很少被查询的。
所以我这里设计了两个订单表,一个是针对用户的,一个是针对商家和管理者的。
用户订单表UOrderId根据订单的后两位(也就是生成订单id时的用户id后两位),进行分库分表,这样分得的订单表中,同一个用户的订单一定是在一个表中的,使用mycat查询的时候,减少了mycat的计算等的操作。
商家订单表OOrderId根据订单产生的时间进行分库分表,我们按照一个月一个月分表,分为12个表,商家和管理者查询这个表,由于经常查看的表只有几个,所以,只会查询特定的几个表,减少查询的复杂度。
4、扩容问题
由于订单系统不仅会通过订单号查找订单,还有可能会通过用户id查找,通过商家id查找,查找所有订单等,但是无论是哪种身份的用户查询都有一个特性,就是很少会查询三个月之前的数据,所以我们可以考虑吧三个月之前的数据迁移到历史数据库中,给新的数据腾空间,从而解决容量增长的问题。
例如:我们可以在3,6,9,12月份的月底进行数据迁移,在6月底,将3月之前的数据都迁移到历史数据库中,历史数据库不要求有多高的性能,只要空间足够就可以,节约成本。
二、使用MQ,起缓冲作用,缓解并发问题
这里我们在生成订单的时候,不直接调用生成订单的接口,而是将订单信息发送到MQ中,利用Mq队列先进先出的特性,一个是使用MQ系统做缓冲作用,还有就是作为MQ的消费者,一定是一个一个处理订单,所以,减少了订单系统的压力,也减少了并发。
四、订单系统数据库设计
DROP TABLE IF EXISTS `xc_order_item`;
CREATE TABLE `xc_order_item` (
`item_id` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '商品id',
`order_id` varchar(50) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '订单id',
`num` int(10) DEFAULT NULL COMMENT '商品购买数量',
`title` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品标题',
`price` double DEFAULT NULL COMMENT '商品单价',
`total_fee` double DEFAULT NULL COMMENT '商品总金额',
`pic_path` varchar(600) COLLATE utf8_bin DEFAULT NULL COMMENT '商品图片地址',
`created` datetime DEFAULT NULL COMMENT '创建时间',
`extend1` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`extend2` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`extend3` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`skuid` bigint(20) NOT NULL DEFAULT '0' COMMENT 'skuid',
PRIMARY KEY (`order_id`),
KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='订单商品表';
CREATE TABLE `xc_order_o` (
`order_id` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '订单id',
`payment` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '实付金额。精确到2位小数;单位:元。如:200.07,表示:200元7分',
`payment_type` int(2) DEFAULT NULL COMMENT '支付类型,1、在线支付,2、货到付款',
`post_fee` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '邮费。精确到2位小数;单位:元。如:200.07,表示:200元7分',
`status` int(10) DEFAULT NULL COMMENT '状态:1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭',
`create_time` datetime DEFAULT NULL COMMENT '订单创建时间',
`update_time` datetime DEFAULT NULL COMMENT '订单更新时间',
`payment_time` datetime DEFAULT NULL COMMENT '付款时间',
`consign_time` datetime DEFAULT NULL COMMENT '发货时间',
`end_time` datetime DEFAULT NULL COMMENT '交易完成时间',
`close_time` datetime DEFAULT NULL COMMENT '交易关闭时间',
`shipping_name` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流名称',
`shipping_code` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流单号',
`user_id` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '用户id',
`buyer_message` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '买家留言',
`buyer_nick` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '买家昵称',
`buyer_rate` int(2) DEFAULT NULL COMMENT '买家是否已经评价',
`extend1` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`extend2` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`extend3` varchar(255) COLLATE utf8_bin DEFAULT NULL,
UNIQUE KEY `order_id` (`order_id`) USING BTREE,
KEY `create_time` (`create_time`),
KEY `buyer_nick` (`buyer_nick`),
KEY `status` (`status`),
KEY `payment_type` (`payment_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='订单基本信息表';
CREATE TABLE `xc_order_shipping` (
`order_id` varchar(50) NOT NULL COMMENT '订单ID',
`receiver_name` varchar(20) DEFAULT NULL COMMENT '收货人全名',
`receiver_phone` varchar(20) DEFAULT NULL COMMENT '固定电话',
`receiver_mobile` varchar(30) DEFAULT NULL COMMENT '移动电话',
`receiver_address` varchar(200) DEFAULT NULL COMMENT '收货地址,如:xx路xx号',
`receiver_zip` varchar(6) DEFAULT NULL COMMENT '邮政编码,如:310001',
`created` datetime DEFAULT NULL COMMENT '创建时间',
`updated` datetime DEFAULT NULL COMMENT '更新时间',
`extend1` varchar(255) DEFAULT NULL,
`extend2` varchar(255) DEFAULT NULL,
`extend3` varchar(255) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单用户基本信息表';
CREATE TABLE `xc_order_u` (
`order_id` varchar(50) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '订单id',
`payment` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '实付金额。精确到2位小数;单位:元。如:200.07,表示:200元7分',
`payment_type` int(2) DEFAULT NULL COMMENT '支付类型,1、在线支付,2、货到付款',
`post_fee` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '邮费。精确到2位小数;单位:元。如:200.07,表示:200元7分',
`status` int(10) DEFAULT NULL COMMENT '状态:1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭',
`create_time` datetime DEFAULT NULL COMMENT '订单创建时间',
`update_time` datetime DEFAULT NULL COMMENT '订单更新时间',
`payment_time` datetime DEFAULT NULL COMMENT '付款时间',
`consign_time` datetime DEFAULT NULL COMMENT '发货时间',
`end_time` datetime DEFAULT NULL COMMENT '交易完成时间',
`close_time` datetime DEFAULT NULL COMMENT '交易关闭时间',
`shipping_name` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流名称',
`shipping_code` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流单号',
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`buyer_message` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '买家留言',
`buyer_nick` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '买家昵称',
`buyer_rate` int(2) DEFAULT NULL COMMENT '买家是否已经评价',
`extend1` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`extend2` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`extend3` varchar(255) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`order_id`),
UNIQUE KEY `order_id` (`order_id`) USING BTREE,
KEY `create_time` (`create_time`),
KEY `buyer_nick` (`buyer_nick`),
KEY `status` (`status`),
KEY `payment_type` (`payment_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='订单基本信息表';
数据库截图如下:
三、订单系统流程