上篇文章讲解了传统数据库的一些设计注意点。
本篇为第二篇,在大数据量的情况下,如何去提前设计这个表结构,来达到一个比较好的效果。对于团队,对于后续的维护和扩展都带来更大的便利。
自增id还是可以有,但是不是必须的了。但是建议还是每张表中有一个自增id。为什么,还是那句话,做数据查询,迁移,排序的时候,有着天然的一些优势。
这个标识无论是token,还是其他例如订单的订单号或者其他唯一标识都行。重点是唯一,不只是在单系统中唯一,而是需要在并发的情况,也能够保持唯一。
关于分布式id的生成方案,网上已经有很多了,这里就不重复了。谷歌搜索搜索,自己看下原理,跑跑demo,能够满足自己业务的最大并发情况下的唯一即可。
比如说你未来几年的最大并发也就是100,搞个能支持在几千并发下不会出现标识重复的实现方案即可,并发几万,几十万,真的需要吗?
后续如果真的能够达到几万并发,那说明什么?说明业务火爆了啊。难道还抽不出时间,抽不出人来做一个id生成方案的改造?这里有比较重要的一点,不要太过超前设计,没必要,也没那个时间。
创建时间和修改时间还是要有的,而且建议时间精确到毫秒级别,在上一篇,我没有说精确多少,那是因为并发不高,秒级完全够了。但是在大数据量的情况下,可能一秒有几十、几百、上千、上万的数据新增都是有可能的。那么秒级在这种情况下完全就不够看了,选择毫秒级别是一个比较好的选择。
前面的唯一标识/创建时间可以说就是为了这步准备的。
但是怎么来设计分库分表,选择什么方式,范围还是hash,选择哪个字段,还是选择几个字段。平滑迁移还是停机迁移。
这些都没有唯一答案。只能是根据场景来区分不同的情况。下面举几个例子来进行一个讲解,不是标准答案,同一个场景为了满足不同的需求,也可能有不同的一个设计。
例如,订单每日新增千万级,那么在这个情况下。我们还需要区分一下。
那么强烈建议按照时间维度进行分库分表。也强烈建议在订单号中将时间戳放进去。
优点:
单表的大小是可以预知的,一天多少订单量,一个月多少订单量
非常便于水平扩展,后期如果想对整个分片集群扩容时,只需要添加库表即可,不需要对已经存在的分片数据进行迁移。使用订单号进行范围查找时,可以快速定位查询,避免了跨片查询的问题。
缺点:
最近的订单会存在着热点数据,可以通过其他方式进行解决,例如缓存等
不包含时间戳,你可以选择创建时间来做范围分片。或者使用订单号来做hash分片,也就是取模运算分片。
hash分片的缺点就是后期扩容会涉及到老数据的迁移,但是现在有一种方案可以避免该缺点,那就是使用虚节点,先占位,但不使用,需要的节点需要是2的次方个才行。大家可以去网上了解一下,这里就不展开了。另外一个缺点就是跨片查询的性能问题,当查询条件中没有订单号的时候,会无法定位到数据库表,所以会遍历所有的库表,进行查询,再在内存中合并数据,取最小集返回,在这种情况下,分库分表反而会成为累赘。
其他一些分库分表带来的事务问题大家可以看看现在的一些分布式事务解决方案,都还挺不错的。阿里的Seata可以了解一下。
最后,分库分表,并不是一定要分库的,也可以只分表,这样很多分库分表的问题就不存在了。分库分表还是要跟进实际的数据增长速度来评估,比如说,每年数据才几十万或者百万,那么没有必要进行一个过渡设计,单表即可。等数据库到了瓶颈,可以再考虑优化。
很多时候,瓶颈也不一定是在数据库。
在这里,对于性能优化提一句,因为自己也刚完成一个性能优化的需求不久,提升性能2倍左右。这次优化完全没有动数据库。主要优化点在:同步方法异步调用第三方服务、计算异步处理、批量单次调用、部分不变数据缓存 重点:拿资源(空间、线程)换时间。
当数据量大了之后,其实很多设计和传统的数据库还是没有很大变化的。
主要是要考虑到数据量大之后,该表如果分库分表,那么怎么设计更加合理一点,也许当下不需要分库分表,但是可以给以后少埋点坑。
但是注意,还是那句话,不要过度设计,也不要不去设计。简单的说,可以预估到以后的业务每日数据量新增是万级几十万以上的,就可以考虑下以后的分表,但是当期并不需要做。但如果是日增百万千万级别,那么这个分库分表肯定是当期就需要进行的。假如是日增几百几千的表,那么就不要花过多时间去考虑什么分库分表的方案了,真的用不上。
建议的一个提前思考时间,1年左右的思考维度设计比较好。即不会超前,也不会因为迭代了一两次业务就有人提出,不知道哪个**设计的结构,又得重新来设计。
最后,能够在技术方案时就明确的事情,绝不留到写代码的时候再去明确!技术方案越清晰(注意:不是说超前设计,这里面有个度,只可意会不可言传),写代码越轻松,团队协作越流畅。
动动小手指 了解更多详情 !