大家好,我是七夕(xī)。正如标题所说,本文将结合自己的亲身经历来介绍三个部分:在线单库单表变多库多表比对历史单表的各种实现方案的优缺点,以及他们不需要当变成多表的时候,需要先画好怎么处理。没有100%完美的解决方案,技术方案始终要结合产品业务来设计。以下解决方案只是通用方法,具体细节可以根据业务场景进行更改和调整。只要能满足业务需求,就是很好的解决方案。不要为了炫耀技术而忽视业务。看完这篇文章,如果后面有人问你改多库多表的打算,那你可以和他好好聊聊。好了,我这里说说我的业务背景,给大家解释一下为什么要多库多表。该计划稍后会延长,请放心。1、业务背景有一个在线运行的数据库,假设是用户库,库中只有一张单表。现在有一个新的需求,这个需求的功能有一定的请求量和数据量。其中,一开始的数据量是百万级。考虑到业务的增加,增加到几千万,几亿都有可能。所以单库单表从数据量的角度来说是不合适的。Q1:如果只是数据量的问题,单库多表可以吗?A1:好的。Q2:那为什么要用多库多表呢?A2:因为一个数据库的连接数是有限的,我怕翻车。上面提到业务有一定的请求量。如果担心一个图书馆来处理,万一网络不好/查的慢/表业务突然有活动等等。如果不小心把连接数填满了,会直接翻车。另外我们公司多库多表的基础设施比较成熟,所以我直接用多库多表。Q3:既然如此,前期可以加单库多表,等量上传完后再加多库多表吗?A3:是的。但是再做一次太累了。比如再一次,你会遇到以下事情:每天都需要检查数据监控是否到了瓶颈。时间再次变化时,开发运维测试业务的调度和执行将发生变化:约定的下一季度推进,结果提前到下一个月进行.这个时候,数据库能不能搞定?有足够的时间进行转型吗?所以,让我们一步一个脚印。弟七夕提醒你:看到这里,如果有人问你单库多表和多库多表的使用场景,你应该知道怎么玩了。2.历史数据处理先说历史数据处理。较少的。这里的内容对应文章开头的第三点:对于历史上存在的单表,不需要变成多表,有两种处理方式。我们知道历史数据在user库,假设业务需要增加到8个库,新表需要添加到2.1方法1中的8个库,user_0,user_1共8个库,...,user_7被添加,使用rename命令,将user数据库的表迁移到user_0数据库,最后删除user数据库。rename命令其实就是重命名,达到切割数据而不是复制的效果。当然,也可以通过复制的方式来迁移数据,不过这里没用。reanme命令使用如下:renametableuser.table_nametouser_0.table_name;2.2方法二添加user_0,user_1,...,user_7共8个数据库,user数据库中数据不变,继续使用。至于选择哪种方式,大多数情况下,我个人认为是可以的,但是如果对历史表本身的要求很高,可以考虑使用方式2,避免0号库压力过大。这是我选择的方式。当用户要访问历史表时,指定到0号数据库的路由即可。顺便省下买个数据库的钱,真香。首先,不考虑任何解决方案,我将最简单的改多库多表的操作按顺序列出:修改服务连接数据库的配置,编写业务代码,添加用户0-7数据库,替换将用户数据库的旧表数据迁移到新添加的user_0库部署服务中,但是如果按照上面的方法,在执行步骤3和4的过程中,如果用户访问原用户库的数据,就会出现问题.具体来说:此时user数据库中的旧数据已经更名并迁移到user_0数据库中,但是因为部署还没有完成,连接数据库的配置还没有更新。所以请求还是会去用户库查询,导致查不到数据,后续的业务逻辑也无法继续顺序执行。用户也会疑惑:“这个地方以前是有数据的,怎么现在全是空的?”因此,需要确定一个合理的升级方案,尽量减少对业务和用户的影响。3.1方案一是最简单的方式。看监控,在没有流量的时候选择,进行数据库变更和服务部署。当然,监控只是过去的事情。不保证功能上线当天流量持续。所以如果想要更稳定,可以发个公告告知用户,xxx功能将在xxx时间段维护,在此期间将无法访问。如果有玩农药(王者荣耀)的朋友应该不会陌生。每次版本更新,都需要停止服用。这是效果。最后,完成后进行回归测试和新功能测试,看功能是否正常。如果正常就可以睡觉了,如果有问题继续修bug解决;如果在公告规定的期限内无法解决评测,那只能回滚改天再战(ban)。PS:如果需要对历史数据进行分库分表,最好进行数据量的对比测试。因为我这边不涉及历史数据的分库分表,所以这一步就省去了。3.2方案二这个方案会复杂很多,开发量也很大。这里只讲关键步骤,具体的细节我就不一一写了。因为要多写几千字,篇幅太长,估计没有多少人有耐心看完。话虽如此,该方案最大的优势在于业务功能无需关闭,无需熬夜。怎么做?3.2.1历史单表数据处理1、先将user数据库中已有的数据复制到user_0数据库中。2、因为用户库中的数据会被修改和添加。所以,拷贝完成后,数据还是有变化的,所以需要加入双写逻辑,保证user_0库中的数据也能同步到变化。3.对于数据读写,都支持开关控制,可以控制向哪个数据库请求数据读写。4、服务更新完成后,比较两个数据库的数据一致性。没有问题后,开关控制读写数据请求到user_0库。3.2.2新功能多表数据处理是新功能,不需要特别处理。你为什么这么说?因为我们部署服务的顺序一定是先发布操作数据库的底层服务,发布完成后,再发布使用底层服务的应用服务。因此作为业务功能入口的应用服务还没有发布,此时没有新的功能数据到达底层服务。如果不能保证这个顺序,你想打开函数入口,用户请求进来后,如果底层服务发现找不到表,会直接报错吗?所以才会有上面说的发布顺序。只要发布顺序正确,这个新功能的数据不需要特殊处理。3.3方案优缺点比较实际上,两种方案是相辅相成的,一种方案的优点是解决了另一种方案的缺点。七喜用一张表来总结一下:优缺点方案一操作简单,不用写复杂的代码保证有流量的时候业务正常执行很累,熬夜太酸;部分服务会被停用,影响用户体验方案二无需停业,不会影响用户开发成本。最后,你问我一开始选择的方案是什么?那肯定是计划一,大不了熬夜。否则,这辈子也不可能制定出这么麻烦的计划,这么紧的工期。如果有问题,如果有严重问题,将由人工处理。yyds文章首发公众号:七夕在学习Java,持续产出原创Java后台干货。如果对你有帮助,临走前能不能点个赞?
