一个完整的项目复盘到底要怎么做?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个完整的项目复盘到底要怎么做?相关的知识,希望对你有一定的参考价值。

复盘,是运营必不可少的能力,小到一次买菜的经历,大到百亿千亿的投资项目,都可以通过复盘来总结规律、提升水平。


简单说来,复盘可以达到的效果有两条:

    优化弱项,强化强项

    明确自己的价值,明确工作的价值

    那么,复盘到底该怎么做呢?或者说,做好复盘有比较高效、实用的方法吗?有的。

    以下内容来源于我工作中的思考,同时参考了柳传志的关于复盘的方法论,力图展现一个完整的、可实践的项目复盘流程。

复盘首先是要做的是事实陈述,一个有效的AAR(After Action Review)必须建立在“铁的事实”的基础上,如果现实难以陈述清楚,并取得一致,将导致复盘进展缓慢或无法深入下去。

一旦事实确定下来了,就开始诊断、分析存在差异的原因,找出导致成功或失败的根本原因后进行规律总结。明白为什么会成功、哪些关键行为起了作用、这些行为有没有适用条件,对于提高后续行动的成功率有没有价值。

一个完整的复盘。包括如下四个步骤:目标回顾、结果陈述、过程分析、规律总结。

彼此坦诚剖析,既不推卸责任,也不妄自菲薄,而是尽可能地呈现一个完整真实的项目流程。每个参与者都有平等的发言权,都能真实地表达想法。

要有专人控制时间和记录要点,开会最忌讳的就是不着边际地开得又臭又长,控制每个部分的时间很重要,另外记录要点也是一种会议成果的输出,有利于总结经验并开展下一步行动。

参考技术A

如何做好项目复盘?

1、什么是项目复盘?

项目复盘不只要对过去的工作进行回顾,还要找出问题及解决方案。项目复盘包括:

(1)情景回顾

(2)问题梳理

(3)寻找解决方法

(4)总结经验教训

(5)为组织过程资产添砖加瓦

2、什么时候复盘?

通常来说,我们会在一个项目结束之后进行复盘。但问题不会等到结束之后才出现,所以需要我们要以较高的频率进行复盘。

可以在项目出现问题的时候进行复盘,以找出解决方案;可以每天进行复盘,及时梳理,或选择在每周五、月末进行复盘;还可以在里程碑节点结束时复盘;敏捷项目则可以在每个迭代结束时进行复盘。

3、项目复盘做什么?

如果条件允许,可以进行项目全过程回顾,如大型的年度复盘;

如果没那么多时间,可进行关键阶段回顾,如里程碑节点复盘、某个问题的复盘。

无论是以上哪一种复盘,总结经验教训都是要点。包括团队方面的总结和个人方面的总结。

4、项目复盘需要谁参加?

建议参与过项目的人,还有承担着关键角色、从头到尾参与项目的人,都要参加。

(1)PM-项目经理

(2)Tech lead-技术负责人

(3)BA-需求分析

(4)QA-质量保证

(5)Dev-开发人员

(6)项目发起人及其他高管

(7)商务

不同的角色会有不同的视角,不同时期的人会对项目有不同程度的理解和输入,所以项目参与者很关键。

值得一提的是,客户也是项目重要的相关方,他的意见也很重要,要不要带客户复盘呢?

Ps:如果是敏捷项目,要带客户参与很关键;如果是传统项目,不要带,客户参与会导致真相沉底,大家没法表达出自己的真实想法。

5、项目复盘的步骤有哪些?

一般的复盘方法包括十步复盘法、GRAI复盘法等。但是,为了给大家节省时间以便加班,圈粉们已经总结出了一套可以让项目经理直接套用的步骤模板,总共分为8步。

项目复盘的步骤

(1)确认会议主题和范围

(2)明确与会人员和主持人

(3)准备好项目所需资料

(4)注重好的开场

(5)顺序研讨、深挖掘

(6)精彩收尾

(7)分享成果

(8)跟进实施&评估改善

是不是很明了?下次复盘的时候,直接套用这个步骤就可以了

6、复盘可以用哪些工具/软件?

(1)使用工具:看板

(2)思维导图:Mindmanager、X-mind等

(3)数字笔记本:Onenote

(4)项目管理软件:MS project、Jira

工具只是帮助,挑选出符合自己团队的使用习惯。复盘是个好方法,可以优化弱项、强化强项,还能明确自己的价值,明确工作的价值。

7、项目复盘的注意事项有哪些?

(1)对每个人的工作都客观评价

(2)问题要犀利、气氛要缓和

(3)选择精明能干的主持人——能够控制住秩序

(4)只讲干货——发生了什么?出现了什么问题?以后遇到了怎么解决?

(5)多开展自我批评

(6)多帮助人解决问题或指明方向

(7)会议时间控制在2-4小时以内

其实项目经理写日报、周报的时候,就是单次简单的复盘,通过每日、每周的反思、迭代,可以不断增加个人能力。

参考技术B

1、回顾活动目标

每一场活动在策划之前都需要明确本场活动的目标是什么?通过设定活动目标,一是体现了举办一场活动的价值,二是通过这些指标可以明确判断此次活动有没有达到预期值。

2、呈现活动结果

既然有活动目标,那么就要有结果将活动的数据具体体现出来。通过对比活动目标与活动结果,比如为什么参会者到达人数比预计少了500人,获取用户销售线索比预期少300个,现场成交额少了600万......

3、深入分析差异

当预期目标与实际效果没有进行匹配,我们就要思考,为什么会有差距?原因到底出现在哪里?利用拆分问题法去解决这个问题,将大问题拆解成小问题进行一一罗列,先从小问题入手。

4、制作复盘数据汇报

客观评论总结出自己活动出现所有的问题,寻找改正的方法,保证下一次会议不再出现类似问题。复盘其实就是一个学习和总结的过程,通过发现问题,解决问题,对现存在的方法不断进行优化迭代,保证每场会议都能高效完成指标。

这些内容都是来自于“百格说”公众号,如果想要更详细的了解关于复盘的知识,可以去关注一下。

参考技术C 每天10分钟,7天学会个人复盘精髓

朋友,好久不见!

为了写这篇文章,四爷是日坐愁城!

好,直说吧!

不迷信于厚厚一本书的个人复盘方法,看看四爷的方法,你完全可以复制。

真的假的?真的!

微信张小龙说:“极简方能不被超越”。

是的,四爷以为:“简洁的才是高效的。”

个人复盘本来就是一个需要变成习惯性的行为。过于复杂的方法论容易让你忘了箭靶——当初的原始目的,也就是所谓的初心。

有些伙伴对于个人复盘很有兴趣,并尝试行动,但是看过某些博士、专业作家的所谓系统化、理论化的理念,比如:个人复盘九步法,引导师等……好似没有这些就不能个人复盘,更不能称之为个人复盘。

其实,四爷认为再好的方法如果不能“为我所用”,那都跟你没有一点关系,简单说,没用!

透过现象看本质,规律性地找寻出得失,然后快速分析主要的原因1-3点即可,接下来找到相应的对应方法,下一步就是计划啦!

为什么有些伙伴说,个人复盘了,但是感觉作用不大呢?

抓本质,抓本质!

本质就是三个字——抓得失!

得失背后对应原因!

原因背后一定有对策,对策对应改进的策略和路径。

基于策略,制定行动计划,如此一个完整的个人复盘循环就完成了。

相信四爷,还是那句话,高效的方法往往都是简单的 -- 大道至简。

你想过吗,做成一件事的过程是什么?

就像把大象放进冰箱的步骤一样,开门-放进大象-关门。

就三步!

想要办成一件事无非是:目标-路径-资源。

事情完成,还是三件事:结果-得失-下一步!

从始至终,抓住主线,行动是贯穿成事儿的关键。

任何时候,我们都是为了更好的行动,所有的思考都是导向结果,结果必然与我们的初心有差距,差距是我们要比对“靶心”,以便于达到更好的下一次结果。

因此,个人复盘是为了改进,做的更好,不是找自己的“茬儿”,而是“发现亮点”,做的更好!

你要记住,行为是策略的反映。

说了那么多,具体怎么做呢?非常简洁的步骤。

1.拿出一张纸,写出下面的三个问题:

1)做这件事时,我当初的目的(初心)是?(对标)
2)达到预期了吗?为什么?对我的启发是?(Top3)
3)如果再来一次,如何做?关键举措/策略是?(行动计划)

就这么三步。

2.拿出第二张纸,扪心自问两个问题:

如果,你还想做的更细致一点,可以增加一步,包括:2个问题!

思考:在这个事情过程中,

1)我有哪些亮点?(找到核心的3个亮点),后续行动进行强化!
2)我的核心提升点?(找到1-3条即可),下一次如何规避?

OK,这是个人复盘中“扪心自问”的一个核心技巧!每一次个人复盘的过程中,都要问自己这个问题。

3.连续7天,每天10分钟,按照前两个步骤。

每天10分钟,连续7天,你就可以学会个人复盘的核心精髓。

记住,一定要先看亮点,而后再看启发,提升点!鼓足勇气,真正面对自己,对于亮点,开心的接受,强化正向行为,反馈到自己的脑海,做的更优秀!

记住,不要再用内容的个人复盘来逃避行为上驱动力的不足了。先提亮点,而后反思提升点,避免下一次继续掉坑!

第一次认真和自己对话,你变好的过程才会开始。这样的个人复盘,才有价值。

最后,再说个小技巧,复盘一定要“用纸写下来,用纸写下来,用纸写下来”。

学复盘,找四爷,我是仲四爷!
参考技术D 主要包括,目标回顾、结果陈述、过程分析以及规律总结。

太完整了!一个亿级分库分表项目的实战全过程解析

分库分表的文章网上非常多,但是大多内容比较零散,以讲解知识点为主,没有完整地说明一个大表的切分、新架构设计、上线的完整过程。


因此,我结合去年做的一个大型分库分表项目,来复盘一下完整的分库分表从架构设计到发布上线的实战总结。


一、前言


为什么需要做分库分表?这个相信大家多少都有所了解。


海量数据的存储和访问成为了MySQL数据库的瓶颈问题,日益增长的业务数据,无疑对MySQL数据库造成了相当大的负载,同时对于系统的稳定性和扩展性提出很高的要求。


而且单台服务器的资源(CPU、磁盘、内存等)总是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。


目前来说一般有两种方案。


  • 一种是更换存储,不使用MySQL,比如可以使用HBase、polarDB、TiDB等分布式存储;

  • 如果出于各种原因考虑,还是想继续使用MySQL,一般会采用第二种方式,那就是分库分表。


文章开头就说了,网上分库分表文章很多,对知识点讲解比较多,因此,本文将不再过多赘述分库分表方案的范式处理。


而是专注于梳理分库分表从架构设计到发布上线的完整过程,同时总结其中的注意事项和最佳实践。包括五个部分:


  • 业务重构

  • 存储架构设计

  • 改造和上线

  • 稳定性保障

  • 项目管理


尤其是各个阶段的最佳实践,都是血与泪凝聚的经验教训。


二、第一阶段:业务重构(可选)


对于微服务划分比较合理的分库分表行为,一般只需要关注存储架构的变化,或者只需要在个别应用上进行业务改造即可,一般不需要着重考虑“业务重构” 这一阶段,因此,这一阶段属于“可选”。


本次项目的第一大难点,在于业务重构。


而本次拆分项目涉及到的两张大表A和B,单表将近八千万的数据,是从单体应用时代遗留下来的,从一开始就没有很好的领域驱动/MSA架构设计,逻辑发散非常严重,到现在已经涉及50+个在线服务和20+个离线业务的的直接读写。


因此,如何保证业务改造的彻底性、全面性是重中之重,不能出现有遗漏的情况。


另外,表A 和 表B 各自有二、三十个字段,两表的主键存在一一对应关系,因此,本次分库分表项目中,还需要将两个表进行重构融合,将多余/无用的字段剔除。


1、查询统计


在线业务通过分布式链路追踪系统进行查询,按照表名作为查询条件,然后按照服务维度进行聚合,找到所有相关服务,写一个文档记录相关团队和服务。


这里特别注意下,很多表不是只有在线应用在使用,很多离线算法和数据分析的业务也在使用,这里需要一并的梳理好,做好线下跨团队的沟通和调研工作,以免切换后影响正常的数据分析。


2、查询拆分与迁移


创建一个jar包,根据2.1的统计结果,与服务owner合作将服务中的相关查询都迁移到这个jar包中(本项目的jar包叫projected)。


此处为1.0.0-SNAPSHOT版本。


然后将原本服务内的xxxMapper.xxxMethod( ) 全部改成projectdb.xxxMethod( )进行调用。


这样做有两个好处:


  • 方便做后续的查询拆分分析;

  • 方便后续直接将jar包中的查询替换为改造后 中台服务 的rpc调用,业务方只需升级jar包版本,即可快速从sql调用改为rpc查询。


这一步实际花了几个月,务必梳理各个服务做全面的迁移,不能遗漏,否则可能会导致拆分分析不全面,遗漏了相关字段。


查询的迁移主要由于本次拆分项目涉及到的服务太多,需要收拢到一个jar包,更方便后期的改造。如果实际分库分表项目中仅仅涉及一两个服务的,这一步是可以不做的。


3、联合查询的拆分分析


根据上述收拢的jar包中的查询,结合实际情况将查询进行分类和判断,把一些历史遗留的问题,和已经废弃的字段做一些整理。


以下举一些思考点。


  • 哪些查询是无法拆分的?例如分页(尽可能地改造,实在改不了只能以冗余列的形式)

  • 哪些查询是可以业务上join拆分的?

  • 哪些表/字段是可以融合的?

  • 哪些字段需要冗余?

  • 哪些字段可以直接废弃了?

  • 根据业务具体场景和sql整体统计,识别关键的分表键。其余查询走搜索平台。


思考后得到一个查询改造总体思路和方案。


同时在本项目中需要将两张表融合为一张表,废弃冗余字段和无效字段。


4、新表设计


这一步基于2.3对于查询的拆分分析,得出旧表融合、冗余、废弃字段的结果,设计新表的字段。


产出新表设计结构后,必须发给各个相关业务方进行review,并保证所有业务方都通过该表的设计。有必要的话可以进行一次线下review。


如果新表的过程中,对部分字段进行了废弃,必须通知所有业务方进行确认。


对于新表的设计,除了字段的梳理,也需要根据具体查询,重新设计、优化索引。


5、第一次升级


新表设计完成后,先做一次jar包内sql查询的改造,将旧的字段全部更新为新表的字段。


此处为2.0.0-SNAPSHOT版本。


然后让所有服务升级jar包版本,以此来保证这些废弃字段确实是不使用了,新的表结构字段能够完全覆盖过去的业务场景。


特别注意的是,由于涉及服务众多,可以将服务按照 非核心 与 核心 区分,然后分批次上线,避免出现问题导致严重故障或者大范围回滚。


6、最佳实践


1)尽量不改变原表的字段名称


在做新表融合的时候,一开始只是简单归并表A 和 表B的表,因此很多字段名相同的字段做了重命名。


后来字段精简过程中,删除了很多重复字段,但是没有将重命名的字段改回来。


导致后期上线的过程中,不可避免地需要业务方进行重构字段名。


因此,新表设计的时候,除非必不得已,不要修改原表的字段名称!


2)新表的索引需要仔细斟酌


新表的索引不能简单照搬旧表,而是需要根据查询拆分分析后,重新设计。


尤其是一些字段的融合后,可能可以归并一些索引,或者设计一些更高性能的索引。


7、本章小结


至此,分库分表的第一阶段告一段落。这一阶段所需时间,完全取决于具体业务,如果是一个历史包袱沉重的业务,那可能需要花费几个月甚至半年的时间才能完成。


这一阶段的完成质量非常重要,否则可能导致项目后期需要重建表结构、重新全量数据。


这里再次说明,对于微服务划分比较合理的服务,分库分表行为一般只需要关注存储架构的变化,或者只需要在个别应用上进行业务改造即可,一般不需要着重考虑“业务重构” 这一阶段。


三、第二阶段:存储架构设计(核心)


对于任何分库分表的项目,存储架构的设计都是最核心的部分!


1、整体架构


根据第一阶段整理的查询梳理结果,我们总结了这样的查询规律。


  • 80%以上的查询都是通过或者带有字段pk1、字段pk2、字段pk3这三个维度进行查询的,其中pk1和pk2由于历史原因存在一一对应的关系;

  • 20%的查询千奇百怪,包括模糊查询、其他字段查询等等。


因此,我们设计了如下的整体架构,引入了数据库中间件、数据同步工具、搜索引擎(阿里云opensearch/ES)等。


下文的论述都是围绕这个架构来展开的。



1) MySQL分表存储


MySQL分表的维度是根据查询拆分分析的结果确定的。


我们发现pk1pk2pk3可以覆盖80%以上的主要查询。让这些查询根据分表键直接走MySQL数据库即可。


原则上一般最多维护一个分表的全量数据,因为过多的全量数据会造成存储的浪费、数据同步的额外开销、更多的不稳定性、不易扩展等问题。


但是由于本项目pk1和pk3的查询语句都对实时性有比较高的要求,因此,维护了pk1和pk3作为分表键的两份全量数据。


而pk2和pk1由于历史原因,存在一一对应关系,可以仅保留一份映射表即可,只存储pk1和pk2两个字段。


2)搜索平台索引存储


搜索平台索引,可以覆盖剩余20%的零散查询。


这些查询往往不是根据分表键进行的,或者是带有模糊查询的要求。


对于搜索平台来说,一般不存储全量数据(尤其是一些大varchar字段),只存储主键和查询需要的索引字段,搜索得到结果后,根据主键去mysql存储中拿到需要的记录。


当然,从后期实践结果来看,这里还是需要做一些权衡的:


  • 有些非索引字段,如果不是很大,也可以冗余进来,类似覆盖索引,避免多一次sql查询;

  • 如果表结构比较简单,字段不大,甚至可以考虑全量存储,提高查询性能,降低mysql数据库的压力。


这里特别提示,搜索引擎和数据库之间同步是必然存在延迟的。所以对于根据分表id查询的语句,尽量保证直接查询数据库,这样不会带来一致性问题的隐患。


3)数据同步


一般新表和旧表直接可以采用 数据同步 或者 双写的方式进行处理,两种方式有各自的优缺点。


太完整了!一个亿级分库分表项目的实战全过程解析


一般根据具体情况选择一种方式就行。


本次项目的具体同步关系见整体存储架构,包括了四个部分:


①旧表到新表全量主表的同步


一开始为了减少代码入侵、方便扩展,采用了数据同步的方式。而且由于业务过多,担心有未统计到的服务没有及时改造,所以数据同步能避免这些情况导致数据丢失。


但是在上线过程中发现,当延迟存在时,很多新写入的记录无法读到,对具体业务场景造成了比较严重的影响。(具体原因参考4.5.1的说明)


因此,为了满足应用对于实时性的要求,我们在数据同步的基础上,重新在3.0.0-SNAPSHOT版本中改造成了双写的形式。


②新表全量主表到全量副表的同步


③新表全量主表到映射表到同步


④新表全量主表到搜索引擎数据源的同步


②、③、④都是从新表全量主表到其他数据源的数据同步,因为没有强实时性的要求,因此,为了方便扩展,全部采用了数据同步的方式,没有进行更多的多写操作。


2、容量评估


在申请MySQL存储和搜索平台索引资源前,需要进行容量评估,包括存储容量和性能指标。


具体线上流量评估可以通过监控系统查看QPS,存储容量可以简单认为是线上各个表存储容量的和。


但是在全量同步过程中,我们发现需要的实际容量的需求会大于预估,具体可以看3.4.6的说明。


具体性能压测过程就不再赘述。


3、数据校验


从上文可以看到,在本次项目中,存在大量的业务改造,属于异构迁移。


从过去的一些分库分表项目来说,大多是同构/对等拆分,因此不会存在很多复杂逻辑,所以对于数据迁移的校验往往比较忽视。


在完全对等迁移的情况下,一般确实比较少出现问题。


但是,类似这样有比较多改造的异构迁移,校验绝对是重中之重!!


因此,必须对数据同步的结果做校验,保证业务逻辑改造正确、数据同步一致性正确。这一点非常非常重要。


在本次项目中,存在大量业务逻辑优化以及字段变动,所以我们单独做了一个校验服务,对数据的全量、增量进行校验。


过程中提前发现了许多数据同步、业务逻辑的不一致问题,给我们本次项目平稳上线提供了最重要的前提保障!!


4、最佳实践


1) 分库分表引起的流量放大问题


在做容量评估的时候,需要关注一个重要问题。就是分表带来的查询流量放大。


这个流量放大有两方面的原因:


  • 索引表的二次查询。比如根据pk2查询的,需要先通过pk2查询pk1,然后根据pk1查询返回结果;

  • in的分批查询。如果一个select...in...的查询,数据库中间件会根据分表键,将查询拆分落到对应的物理分表上,相当于原本的一次查询,放大为多次查询。(当然,数据库会将落在同一个分表的id作为一次批量查询,而这是不稳定的合并)


因此,我们需要注意:


  • 业务层面尽量限制in查询数量,避免流量过于放大;

  • 容量评估时,需要考虑这部分放大因素,做适当冗余,另外,后续会提到业务改造上线分批进行,保证可以及时扩容;

  • 分64、128还是256张表有个合理预估,拆得越多,理论上会放大越多,因此不要无谓地分过多的表,根据业务规模做适当估计;

  • 对于映射表的查询,由于存在明显的冷热数据,所以我们又在中间加了一层缓存,减少数据库的压力。

2)分表键的变更方案


本项目中,存在一种业务情况会变更字段pk3,但是pk3作为分表键,在数据库中间件中是不能修改的,因此,只能在中台中修改对pk3的更新逻辑,采用先删除、后添加的方式。


这里需要注意,删除和添加操作的事务原子性。当然,简单处理也可以通过日志的方式,进行告警和校准。


3)数据同步一致性问题


我们都知道,数据同步中一个关键点就是(消息)数据的顺序性,如果不能保证接受的数据和产生的数据的顺序严格一致,就有可能因为(消息)数据乱序带来数据覆盖,最终带来不一致问题。


我们自研的数据同步工具底层使用的消息队列是kakfa,,kafka对于消息的存储,只能做到局部有序性(具体来说是每一个partition的有序)。我们可以把同一主键的消息路由至同一分区,这样一致性一般可以保证。但是,如果存在一对多的关系,就无法保证每一行变更有序,见如下例子。



那么需要通过反查数据源获取最新数据保证一致性。


但是,反查也不是“银弹“,需要考虑两个问题。


  • 如果消息变更来源于读写实例,而反查 数据库是查只读实例,那就会存在读写实例延迟导致的数据不一致问题。因此,需要保证 消息变更来源 和 反查数据库 的实例是同一个;

  • 反查对数据库会带来额外性能开销,需要仔细评估全量时候的影响。


4)数据实时性问题


延迟主要需要注意几方面的问题,并根据业务实际情况做评估和衡量。


  • 数据同步平台的秒级延迟;

  • 如果消息订阅和反查数据库都是落在只读实例上,那么除了上述数据同步平台的秒级延迟,还会有数据库主从同步的延迟;

  •  宽表到搜索平台的秒级延迟。


只有能够满足业务场景的方案,才是合适的方案。


5)分表后存储容量优化


由于数据同步过程中,对于单表而言,不是严格按照递增插入的,因此会产生很多”存储空洞“,使得同步完后的存储总量远大于预估的容量。


因此,在新库申请的时候,存储容量多申请50%。


具体原因可以参考我的这篇文章


5、本章小结


至此,分库分表的第二阶段告一段落。


这一阶段踩了非常多的坑。


一方面是设计高可用、易扩展的存储架构。在项目进展过程中,也做了多次的修改与讨论,包括mysql数据冗余数量、搜索平台的索引设计、流量放大、分表键修改等问题。


另一方面是“数据同步”本身是一个非常复杂的操作,正如本章最佳实践中提及的实时性、一致性、一对多等问题,需要引起高度重视。


因此,更加依赖于数据校验对最终业务逻辑正确、数据同步正确的检验!


在完成这一阶段后,可以正式进入业务切换的阶段。需要注意的是,数据校验仍然会在下一阶段发挥关键性作用。


四、第三阶段:改造和上线(慎重)


前两个阶段完成后,开始业务切换流程,主要步骤如下:


  • 中台服务采用单读 双写 的模式;

  • 旧表往新表开着数据同步;

  • 所有服务升级依赖的projectDB版本,上线RPC,如果出现问题,降版本即可回滚(上线成功后,单读新库,双写新旧库)

  • 检查监控确保没有 中台服务 以外的其他服务访问旧库旧表;

  • 停止数据同步;

  • 删除旧表。


1、查询改造


如何验证我们前两个阶段设计是否合理?能否完全覆盖查询的修改 是一个前提条件。


当新表设计完毕后,就可以以新表为标准,修改老的查询。


以本项目为例,需要将旧的sql在 新的中台服务中 进行改造。


1)读查询的改造


可能查询会涉及以下几个方面:


  • 根据查询条件,需要将pk1和pk2的inner join改为对应分表键的新表表名;

  • 部分sql的废弃字段处理;

  • 非分表键查询改为走搜索平台的查询,注意保证语义一致;

  • 注意写单测避免低级错误,主要是DAO层面。


只有新表结构和存储架构能完全适应查询改造,才能认为前面的设计暂时没有问题。


当然,这里还有个前提条件,就是相关查询已经全部收拢,没有遗漏。


2) 写查询的改造


除了相关字段的更改以外,更重要的是,需要改造为旧表、新表的双写模式。


这里可能涉及到具体业务写入逻辑,本项目尤为复杂,需要改造过程中与业务方充分沟通,保证写入逻辑正确。


可以在双写上各加一个配置开关,方便切换。如果双写中发现新库写入有问题,可以快速关闭。


同时,双写过程中不关闭 旧库到新库 的数据同步。


为什么呢?主要还是由于我们项目的特殊性。由于我们涉及到几十个服务,为了降低风险,必须分批上线。因此,存在比较麻烦的中间态,一部分服务是老逻辑,一部分服务是新逻辑,必须保证中间态的数据正确性,具体见4.5.1的分析。


2、服务化改造


为什么需要新建一个 服务来 承载改造后的查询呢?


一方面是为了改造能够方便的升级与回滚切换,另一方面是为了将查询收拢,作为一个中台化的服务来提供相应的查询能力。


将改造后的新的查询放在服务中,然后jar包中的原本查询,全部替换成这个服务的client调用。


同时,升级jar包版本到3.0.0-SNAPSHOT。


3、服务分批上线


为了降低风险,需要安排从非核心服务到核心服务的分批上线。


注意,分批上线过程中,由于写服务往往是核心服务,所以安排在后面。可能出现非核心的读服务上线了,这时候会有读新表、写旧表的中间状态。


1) 所有相关服务使用 重构分支 升级projectdb版本到3.0.0-SNAPSHOT并部署内网环境;


2) 业务服务依赖于 中台服务,需要订阅服务;


3) 开重构分支(不要与正常迭代分支合并),部署内网,内网预计测试两周以上。


使用一个新的 重构分支 是为了在内网测试两周的时候,不影响业务正常迭代。每周更新的业务分支可以merge到重构分支上部署内网,然后外网使用业务分支merge到master上部署。


当然,如果从线上线下代码分支一致的角度,也可以重构分支和业务分支一起测试上线,对开发和测试的压力会较大。


4)分批上线过程中,如果碰到依赖冲突的问题,需要及时解决并及时更新到该文档中;


5)服务上线前,必须要求业务开发或者测试,明确评估具体api和风险点,做好回归。


这里再次提醒,上线完成后,请不要漏掉离线的数据分析业务!请不要漏掉离线的数据分析业务!请不要漏掉离线的数据分析业务!


4、旧表下线流程


1)检查监控确保没有中台服务以外的其他服务访问旧库旧表;


2)检查数据库上的sql审计,确保没有其他服务仍然读取旧表数据;


3)停止数据同步;


4)删除旧表。


5、最佳实践


1) 写完立即读可能读不到


在分批上线过程中,遇到了写完立即读可能读不到的情况。由于业务众多,我们采用了分批上线的方式降低风险,存在一部分应用已经升级,一部分应用尚未升级的情况。未升级的服务仍然往旧表写数据,而升级后的应用会从新表读数据,当延迟存在时,很多新写入的记录无法读到,对具体业务场景造成了比较严重的影响。


延迟的原因主要有两个:


  • 写服务还没有升级,还没有开始双写,还是写旧表,这时候会有读新表、写旧表的中间状态,新旧表存在同步延迟;

  • 为了避免主库压力,新表数据是从旧表获取变更、然后反查旧表只读实例的数据进行同步的,主从库本身存在一定延迟。


解决方案一般有两种:


  • 数据同步改为双写逻辑;

  • 在读接口做补偿,如果新表查不到,到旧表再查一次。


2) 数据库中间件唯一ID替换自增主键(划重点,敲黑板)


由于分表后,继续使用单表的自增主键,会导致全局主键冲突。因此,需要使用分布式唯一ID来代替自增主键。各种算法网上比较多,本项目采用的是数据库自增sequence生成方式。


数据库自增sequence的分布式ID生成器,是一个依赖Mysql的存在, 它的基本原理是在Mysql中存入一个数值, 每有一台机器去获取ID的时候,都会在当前ID上累加一定的数量比如说2000, 然后把当前的值加上2000返回给服务器。这样每一台机器都可以继续重复此操作获得唯一id区间。


但是仅仅有全局唯一ID就大功告成了吗?显然不是,因为这里还会存在新旧表的id冲突问题。


因为服务比较多,为了降低风险需要分批上线。因此,存在一部分服务还是单写旧表的逻辑,一部分服务是双写的逻辑。


这样的状态中,旧表的id策略使用的是auto_increment。如果只有单向数据来往的话(旧表到新表),只需要给旧表的id预留一个区间段,sequence从一个较大的起始值开始就能避免冲突。


但该项目中,还有新表数据和旧表数据的双写,如果采用上述方案,较大的id写入到旧表,旧表的auto_increment将会被重置到该值,这样单写旧表的服务产生的递增id的记录必然会出现冲突。


所以这里交换了双方的区间段,旧库从较大的auto_increment起始值开始,新表选择的id(也就是sequence的范围)从大于旧表的最大记录的id开始递增,小于旧表auto_increment即将设置的起始值,很好的避免了id冲突问题。


①切换前


sequence的起始id设置为当前旧表的自增id大小,然后旧表的自增id需要改大,预留一段区间,给旧表的自增id继续使用,防止未升级业务写入旧表的数据同步到新库后产生id冲突。


②切换后


无需任何改造,断开数据同步即可。


③优点


只用一份代码;


切换可以使用开关进行,不用升级改造;


如果万一中途旧表的autoincrement被异常数据变大了,也不会造成什么问题。


④缺点


如果旧表写失败了,新表写成功了,需要日志辅助处理。


6、本章小结


完成旧表下线后,整个分库分表的改造就完成了。


在这个过程中,需要始终保持对线上业务的敬畏,仔细思考每个可能发生的问题,想好快速回滚方案(在三个阶段提到了projectdb的jar包版本迭代,从1.0.0-SNAPSHOT到3.0.0-SNAPSHOT,包含了每个阶段不同的变更,在不同阶段的分批上线的过程中,通过jar包版本的方式进行回滚,发挥了巨大作用),避免造成重大故障。


五、稳定性保障


这一章主要再次强调稳定性的保障手段。作为本次项目的重要目标之一,稳定性其实贯穿在整个项目周期内,基本上在上文各个环节都已经都有提到,每一个环节都要引起足够的重视,仔细设计和评估方案,做到心中有数,而不是靠天吃饭:


  • 新表设计必须跟业务方充分沟通、保证review;

  • 对于“数据同步”,必须有数据校验保障数据正确性,可能导致数据不正确的原因上文已经提到来很多,包括实时性、一致性的问题。保证数据正确是上线的大前提;

  • 每一阶段的变动,都必须做好快速回滚都预案;

  • 上线过程,都以分批上线的形式,从非核心业务开始做试点,避免故障扩大;

  • 监控告警要配置全面,出现问题及时收到告警,快速响应。不要忽略,很重要,有几次出现过数据的问题,都是通过告警及时发现和解决的。

  • 单测,业务功能测试等要充分。


六、项目管理之跨团队协作


关于“跨团队协作”,本文专门拎出来作为一章。


因为在这样一个跨团队的大型项目改造过程中,科学的团队协作是保障整体项目按时、高质量完成的不可缺少的因素。


下面,分享几点心得与体会。


1 、一切文档先行


团队协作最忌“空口无凭”。


无论是团队分工、进度安排或是任何需要多人协作的事情,都需要有一个文档记录,用于追踪进度,把控流程。


2、业务沟通与确认


所有的表结构改造,必须跟相关业务方沟通,对于可能存在的历史逻辑,进行全面梳理;


所有讨论确定后的字段改造,必须由每个服务的Owner进行确认。


3、责任到位


对于多团队多人次的合作项目,每个团队都应该明确一个对接人,由项目总负责人与团队唯一对接人沟通,明确团队完整进度和完成质量。


七、展望


其实,从全文的篇幅就能够看出,本次的分库分表项目由于复杂的业务逻辑改造,费大量的时间和精力,并且非常容易在改造过程中,引起不稳定的线上问题。


本文复盘了整个分库分表从拆分、设计、上线的整体过程,希望能对大家有所帮助。


看到这里,我们会想问一句。所以,有没有更好的方式呢?


也许,未来还是需要去结合业界新的数据库中间件技术,能够快速实现分库分表。


也许,未来还可以引入新的数据存储技术与方案(polardb、tidb、hbase),根本不再需要分库分表呢?


继续跟进新技术的发展,我相信会找到答案。


作者丨阿丸笔记

来源丨阿丸笔记(ID:aone_note)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱editor@dbaplus.cn




2020 Gdevops全球敏捷运维峰会·北京站 即将于12月11日举办,部分精彩议题先睹为快:

  • 腾讯《国产数据库浪潮下的云上实践与思考》

  • 京东《京东超大规模分布式集群下的大数据运维实践》

  • 携程《怎么用ClickHouse建数据平台才撑得起100亿+数据量》

  • 工商银行《ICBC的MySQL转型探索之路》

  • 建设银行《重新发现业务架构:银行数字化转型经验与方法分析》

  • 农业银行《中国农业银行信贷中台及数据中台建设实践》

  • 光大银行《光大银行实时数据仓库应用实践》

  • 民生银行《民生银行智能运维平台实践之路》

  • 华夏银行《银行分布式数据库改造方案实践与探索》

  • 中邮消费金融《敏捷消费金融中台架构下的深度服务治理》

  • 蚂蚁集团《OceanBase的分布式关系数据库探索HTAP之路》

  • 58到家《技术体系建设:架构、质量、中台、后端的战略落地与矛盾破解》

  • 中国联通《数据智能时代:构建能力开放的运营商大数据DataOps体系》


以上是关于一个完整的项目复盘到底要怎么做?的主要内容,如果未能解决你的问题,请参考以下文章

最完整的小红书带货笔记——垂直模式

作为一个研发应该如何进行项目复盘

亿级大表分库分表实战总结(万字干货,实战复盘)

为什么要复盘,要写博客?

直播带货怎么做?直播带货新手入门教程

对于最近工作的一些感悟和复盘