背景
之前看过公司的商城系统,当时遇到一个问题,就是我拿到一个订单号,我竟然不知道怎么去查到这个订单号的详细信息,尴尬了。后来问了商城那边的同事,才知道,公司对订单系统中的表做了分表操作。下面来聊聊。
分库分表的作用
只分库不分表
当数据库的读或者写的QPS过高导致数据库的连接不足了这时候就需要考虑做分库了。通过增加数据库实例的方式,提高系统的并发度
分布式系统,每个系统都有自己一个独立的库,其实这是一种 垂直分库 。将业务杂糅的表,解耦成独立业务的表,放在不同的数据库中,从而解决分布式系统访问压力,原来十个系统都要访问一个数据库,现在十个系统访问不同的十个库。
读写分离,数据库做主从数据库的时候,主库用来写数据,从库用来读数据,从库同步主库的数据,用主库的binlog日志来同步数据变更。这是一种 水平分库 的方式。主库和从库的表结构一致,数据也一致,仅仅是为了解决数据库读多写少的场景。
只分表不分库
当数据库的单表数据量特别的大的时候,因为并发不高,数据库的连接够用,但是存储查询的性能会特别的低,这个时候就需要做分表了,将数据拆分到多张表中,提高读写的性能
大表(字段多)拆成多个小表(字段少),这就是一种 垂直分表 。
订单表的分表,这其实就是一种 水平分表 。因为订单表随着时间的积累,数据会越来越多,到那时候一个订单表的查询和写入会变得特别的慢。例如现在订单表有200亿条数据,但是水平分表成1024张表,每张表大概只有2000万条数据,这个时候的查询与写入操作效率还是很好的。
既分库也分表
两种情况都产生的时候:
当数据库的读或者写的QPS过高导致数据库的连接不足了这时候就需要考虑做分库了。通过增加数据库实例的方式,提高系统的并发度
当数据库的单表数据量特别的大的时候,因为并发不高,数据库的连接够用,但是存储查询的性能会特别的低,这个时候就需要做分表了,将数据拆分到多张表中,提高读写的性能
订单表的分库分表如何做呢?
订单表分表思路
分库这里不阐述,公司只做了分表,没有做分库。其实效果是一样的
公司主要是用用户的UID作为分表的依据。将用户的UID对1024取模,算出对应的下标,然后将该用户的订单存入对应的分表中,主表也会异步写入一份。
![](https://img.haomeiwen.com/i20347625/320fee9eed8a9700.png)
然后订单号也是做特殊处理的:
订单号: 全局唯一ID + 分表下标 + 时间戳
存在的问题
分表后,查询会存在一定的问题
买家(用户UID)维度查询
由于我们是根据用户UID来做分表的,同一个用户的所有订单,都是在同一张表中,每次查询前,使用用户UID对1024取模,得到对应分表的下标,然后进入对应的分表做简单查询就可以了。
订单号维度查询
由于我们的订单号是组合式的,我们可以拿到对应的分表下标,所以在查询前做一步解析订单号操作,拿到分表下标,去对应的分表里面做简单查询就可以了
卖家UID维度查询
方案一:
需要根据卖家UID去不同的分表里面做查询,这个代价太大了。因为我们还有一张主表,所以可以从主表里面查询,这样可能会性能不好,但是这的确是一种解决方案。
方案二:
给每个卖家分配一张表,然后将订单数据同步到对应的卖家UID的数据表中,然后查询的时候针对当前这个卖家对应的订单表查询。代价也是不小的,像淘宝,有几千万的卖家,就需要几千万张卖家订单表,这也很麻烦。
方案三:
借助HBase,ES这样的技术,去单独的存。代价就是需要多使用一种技术,增加一种风险。
总结:
不管如何分库分表都是会存在针对某一维度的查询难得问题,具体就看你的业务能容忍哪种了。
其他字段维度的查询
这个就可以将其他维度的字段作为分词存到ES里面,借助ES的搜索功能做对应的查询操作。
网友评论