一个发自肺腑的问题:分库分表能否无限扩展?工作几年后,我对服务的可用性和可扩展性有了新的疑惑。什么样的疑问?其实就是一个共同的话题:服务扩展的问题。服务演进的正常路径让我们从头开始。1.单体应用每个初创公司基本上都是从SSM、SSH这样的架构开始的。没什么可谈的。基本上每个程序员都经历过。2.RPC应用当业务越来越大时,我们需要对服务进行横向扩展。扩展很简单,只要服务无状态即可,如下图:当业务越来越大的时候,我们的服务关系错综复杂,同时有很多不需要的服务访问连接到DB,而只需要连接到缓存,这样就可以将它们分开,减少宝贵的DB连接。如下图所示:相信大部分公司都处于这个阶段。Dubbo就是为了解决这个问题而诞生的。分库分表如果你公司的产品很火爆,业务持续高速发展,数据越来越多,SQL操作越来越慢,那么数据库就会成为瓶颈,那你肯定会想到分库分表,不管通过IDhash还是range都可以。如下图所示:现在应该没有问题了。不管你有多少用户,多高的并发,我只需要扩展数据库,独立扩展应用,就可以了。这也是本文的标题。分库分表能解决***扩容吗?其实和上面的架构一样,是解决不了的。其实这个问题有点类似于RPC的问题:数据库连接太多!!!通常情况下,因为我们的RPC应用是通过中间件来访问数据库的,所以应用实际上并不知道访问哪个数据库,而访问数据库的规则是由中间件决定的,比如shardingJDBC。这样一来,这个应用就必须连接所有的数据库,就像我们上面的架构图,一个RPC应用需要连接3个mysql,如果有30个RPC应用,每个RPC的数据库连接池大小为8,每个mysql需要维持240个连接。我们知道mysql默认的连接数是100,最大连接数是16384。也就是说,假设每个应用的连接池大小是8,超过2048个应用无法继续连接的话,那就无法继续扩大。请注意,2048并不像看起来那么大,因为每个物理库有许多逻辑库,而且微服务运动如火如荼。你可能会说,我前面加个代理就可以解决连接数的问题了。事实上,代理的性能也会成为一个问题。为什么?proxy的连接数不能超过16384,如果并发超过16384就会变成163840,那么proxy也解决不了问题。我们应该做什么?我们再看一下上面的架构图:我们发现问题出在“每一个RPC应用都要连接所有的库”,导致在扩展应用的同时增加了每个数据库的连接数。即使增加数据库,也解决不了连接数的问题。那我们该怎么办呢?unitization,unitization,听上去很高端,通常在一些XXX会议上,分享“两地三中心左右”、“三地五中心”、“异地多活动”等牛逼的名词有时,unitization也会一起出现。这里不讨论牛逼,只说“数据库连接数过多”的问题。其实思路很简单:我们不让应用连接所有的数据库。假设我们按照范围分成10个库。现在有10个应用程序。我们让每个应用程序只连接到一个图书馆。当应用增加到20个,数据库连接不够用的时候,我们把10个库分成20个,这样无论你扩展多少应用,都可以解决数据库连接过多的问题。注意:这样做的前提是:你必须保证访问你的应用程序的请求请求的数据库必须在这个应用程序中。换句话说,当用户从DNS进来的时候,他们知道他们是要去应用的,所以规则是在DNS之前设置的。虽然这有点夸张,但他们在进入应用程序之前必须知道要去哪个图书馆。所以,这通常需要一个规则,比如用户ID哈希,由配置中心哈希规则广播。这样,所有组件都可以保持一致的规则来正确访问数据库。如下图所示:到这里,我们终于解决了***扩展的问题。***本文从一个单一的应用开始,逐步讲述一个普通后台的演变过程。我们知道,分库分表并不能解决“***扩容”的问题,只有单元化才能解决这个问题。单元化带来了更多的复杂性。但好处是不言而喻的。单元化带来的更多想法。单元化解决了最大扩展的问题,但是我们没有考虑单点的问题,也就是服务的可用性。要知道,我们这里的数据库都是单点的。这是另一个话题——多住异地。限于篇幅,我们下次再说。
