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