随着业务越来越复杂,数据量越来越大,并发量越来越大,数据库的性能越来越低。最后找运维申请了两台机器,让DBA部署了几个实例。想拆分一些业务库,却发现一个库有几百张表,无法拆分和扩展。尴尬!因为数据库它们是强关联在一起的,不能通过增加数据库实例来扩展,这是典型的耦合情况。这种耦合会出现什么样的场景呢?举个栗子。有一个公共用户数据库DB_USER,其中table_user存储一般用户数据:table_user(uid,name,passwd,…)当数据量比较少的时候,并发量比较小,业务没那么复杂,为了提高资源利用率(程序员不考虑资源利用率,更多的是为了方便),业务A也将用户的个性化数据放到这个库中:table_A(uid,业务A的个性化属性)业务A有一个需求,即既要显示用户的公共属性,又要显示业务A的个性化属性。程序员经常这样实现:select*fromtable_user,table_Awheretable_user.uid=table_A.uidandtable_user.uid=$uid没有问题在初始关联查询,单条记录访问时,命中索引,一次性查询所有数据,简单高效。如何产生业务数据耦合?通过join实现业务,一般表table_user和业务表table_A必须存在于一个数据库实例中。如果业务B做同样的事情,业务C做同样的事情,那么就会导致业务是通用的,业务A、业务B、业务C都必须存在于同一个数据库实例中。会出现哪些潜在问题?如果A的业务线上线了一个新功能,不小心进行了全表扫描,数据库CPU就会100%,数据库实例的性能就会下降。由于实例共享,一般业务、业务B和业务C都会受到影响。即某条业务线的数据库性能急剧下降,所有业务都受到影响。这种耦合的历史总是惊人的相似:B业务的大老板第一个在群里发疯:“技术怎么了?为什么系统挂了?””B商家rd一脸无辜:“A商家在线,我们挂了。加几台机器拆分。”B业务rd一脸无奈:“加机器加实例扩容不了。”B业务大老板对2业务rd吼道,“我要扔锅开拖出去祭天”……唉,我又加了几台机器,加了好几个实例,没用,都耦合在一个实例上,容量不能扩容到那么,公共数据库和业务数据库如何解耦呢?第一步:公共数据访问sink服务。还是上面的例子,服务公共用户数据访问后,根据服务原则:业务层只能通过服务RPC接口访问数据;底层用户库是用户服务私有的;任何上游i不允许跨服务用户库访问底层;第二步:垂直拆分,向上接入个性化数据。原始业务端:通过join一次性获取通用数据和个性化业务数据。面向服务+垂直拆分后,变成了两次访问:一次是获取业务数据(业务可以直接调用自己的数据库,也可以做业务服务调用RPC接口);一次获取公共数据(调用通用RPC接口);两种方式相比:前一种方式其实业务代码可能更简单,因为它把业务逻辑放在了SQL语句中,但是导致数据库耦合在一起;后一种方式意味着业务代码会更简单。复杂了,会变成多次访问,原来在SQL中进行的逻辑计算,变成了业务代码中的逻辑计算,但是数据库是解耦的;业务复杂,数据量大,并发老板对扩展性要求更高。架构必须是后者。这时候每个业务都有自己的库,公众有一个公共库:早期:可以放在数据库实例中;后期:很容易添加新的数据库实例去掉用户库或者业务A/B/C分离的库,通过增加机器和实例实现扩容;单个业务数据访问的垂直拆分,公共数据访问服务的下沉,只是一个很小的优化点,但是对于数据库解耦是非常有效的。希望大家每天都有一点收获,这样结构才能好一点。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
