2019的今天我们是否还需要分库分表

2019-04-29

TL,DR: 分库吗?先考虑下微服务;分表吗?先考虑下NoSQL。

什么时候考虑分库分表

首先,“分库分表”作为应对高并发、海量数据的一种技术手段属于实现细节层面的东西。从软件架构的角度看,不属于业务逻辑的核心,而属于技术上的多种选项中的一种。因此是不是需要分库分表、如何分库分表的决策都应该被尽可能的推迟,而业务核心也应该尽可能中立于此类技术决策。

从产品发展的阶段考虑,大致有两种情况。

一种是对原有系统、产品的改造。这种情况下,现有的用户规模、数据量规模是确定的,增长速度也是有历史记录的,因此对于未来的用户规模和数据量能做出比较可靠的预测。这种情况下可以在一开始就考虑是否需要采用特别的应对并发量和数据量的技术。

另一种情况,新的系统、新的解决方案、新的商业模式,这种情况下高并发量、海量数据可能还只存在于商业计划书和PPT上面。此时最重要的是尽快交付核心功能、验证商业模式和解决方案,只随着用户量的增长再逐步实施各种提升性能的措施。当然前提是软件架构的设计能够容纳各种不同的实现技术,当真的需要采用分库分表或其它类似技术时不需要重写核心业务逻辑部分。

我曾经面试过一个架构师,是自己创业失败后再找工作的。他一开始就实现了微服务架构、实现了分库分表,但等到钱花光的那天活跃用户也只有数千人。

分库

一般对分库的解释是将不同的数据表分布到不同的物理数据库中。无论是因为高并发、海量数据、还是业务的复杂度,这确实是一种有效的方式。只是在今天应该首先考虑采用微服务架构。每个微服务都有自己的数据库,自然就实现了分库。但无论是业务逻辑的分离、不同服务节点的灵活部署和扩展,微服务都提供了比简单的分库能做的更多、更好。

而如果不采用微服务,一个Monolith系统却采用分库,除了引入多数据源的复杂性以外,想不出来能有什么好处。

与分库类似的还有一种模式CQRS,在国外的软件社群中似乎对这个概念的讨论似乎更多一些。

CQRS强调对Command (命令)和Read(查询)采用不同的数据模型(Model)。Command Model用于实现业务逻辑,会满足各种范式;Read Model为查询而优化,比如为了减少 join 操作可以违反一些设计范式、可以有数据冗余。CQRS倒不强调物理上的分离,使用同一个物理数据库但不同的表分别支持Command和Read也是可以的。

分表

如果采用了微服务,那么基本上就告别了2PC(两阶段提交)、强一致性。在分布式的环境中,可用性和强数据一致性是不可兼得的。分布式事务即复杂也不可靠,还不如满足于最终一致性即可。事件响应式的应用能弱化微服务之间的耦合,获得更好的扩展性和可靠性。

如果不再强求2PC,那么在数据库类型方面的选择余地一下子就多了很多,可以根据数据模型的特性、业务的特性选择更合适的数据库类型。

很多NoSQL都天生支持分片、集群,比如MongoDB, HBase 等。不需要额外写程序、需要时可方便地加入新节点,等等,实在比自己费劲巴拉地去实现分表算法更方便、可靠。

结论

2019的今天,分库的问题应该随着系统的微服务化的过程来一起考虑。而对于海量数据的情况,应该优先考虑能更好地支持集群的数据库,而不是自己在关系型数据上去实现分表。


后记:最近在知乎的时间线上看到好几篇讲分库分表的文章,故有此文。



blog comments powered by Disqus