Skip to main content

如何从 0 到 1 设计一个复杂系统——以通知系统为例

前言

如果你是一名产品经理,有一天……

  • 产品开始要做商业化了,你需要设计整个产品的经济系统,需要接支付、对账单、用户界面、运营后台……要做的太多了,你根本不知从何入手
  • 你接到了一个新需求,需要支持用户注销帐号,过了几个月,又有一个新需求,需要支持用户注销帐号后恢复,当你跟研发讲解这个功能的时候,他却说,你怎么不早说,之前注销的帐号全都硬删除啦,这个新功能没法做
  • 同事离职了,把通知系统交接给你,让你负责日后的维护,但你发现除了零散的功能 PRD,没有一份文档可以说明整个通知系统是怎么设计的、通知内容是怎么组装的、第三方服务是怎么对接的,全靠同事之间的口口相传 ……

以上的场景,相信产品经理们或多或少都遇到过。初看这些问题,似乎风牛马不相及,但敏锐的同学可能发现了,这些问题都与系统架构(System Architecture)相关。因为很多问题的产生,都是源于最初为了快速上线,对架构设计缺乏性能、扩展性、可维护性等全局考虑,导致后续功能越做越多,越做越乱,功能策划和研发的难度都比较大。

所以,一个希望长期参与市场竞争的产品,它的团队里,少不了架构师这一角色,他需要以更宏观和长期的角度设计产品或其中某个复杂系统,而良好的架构可以让产品在未来拥有更多的可能性、更高的灵活度和更强健的性能,也更易于维护。

虽然架构师通常由研发工程师来充当,但产品经理对于业务场景的理解和预判可能更胜一筹,如果产品经理掌握系统思维,将和研发工程师形成视角的互补,所以作为一名产品经理,本文将结合我的所学和工作经验,以通知系统为例,浅谈系统架构的原则与方法,希望对各位有所助益。

本文受众

如果你也是一名产品经理,本文将帮助你:

  • 掌握系统思维(system thinking),形成一套有助于完成架构工作的指导原则
  • 通过具体例子了解如何定义系统的边界及其内外部的形式与功能,在接到一个系统级别的需求时,能够科学有效地分析需求、确定目标、完成设计
tip

系统思维(system thinking),简单地说,就是把某个疑问、某种状况或某个难题明确地视为一个系统,也就是视为一组相互关联的实体。系统思维不等于系统化地思考 (thinking systematically)。

如果你是一名架构师或者研发工程师你将从本文欣赏到产品经理是如何在关公面前耍大刀的,本文将帮助你:

  • 了解产品经理如何描述用户的场景与需求,以及如何把需求转换为系统目标

名词解释

系统

系统(System)是由一组实体和这些实体之间的关系所构成的集合,其功能要大于这些实体各自的功能之和。

这个定义体现了两个重点:
1.系统是由相互作用或相互联系的实体组成的。
2.实体之间发生相互作用时,会出现一种功能,这种功能大于或不同于这些实体各自所具备的那些功能。

tip

举个 🌰
假如我们把房子视为一个系统,那么房子是由砖块、水泥、钢筋等实体组成的,它拥有了安置人类/动物的功能,这个功能是原来这些实体不具备的,是它们组合到一起时,才涌现出来的。
对应到通知系统,它的实体有通知的发送方、消息体、接收方,当它们组合以后,就实现了通知系统的主要功能——信息传递。

架构

架构(Architecture)就是对系统中的实体以及实体之间的关系所进行的抽象描述。在由人类所构建的系统中,架构可以表述为一系列的决策。

因此,综合以上定义,我们要做的事情,就是通过一系列人为的决策,设计出符合我们预期目标的系统。

战略篇

上面这些理论是不是看得云里雾里的🤣没关系,从这部分开始,我们就要开始实战啦,请跟随我的步伐,一起来看看如何从 0 到 1 设计复杂系统~

假设你加入了一个 SaaS 产品团队,某一天,大佬对你说:小明,看你年纪也不小了,要不要挑战一下设计一个复杂系统?新产品的通知系统就交给你吧!

这时你自信满满,不就一个通知嘛,看起来很简单,给用户搞个通知中心,把通知显示出来不就完事了。

没想到大佬又发话了,又提了几个场景,他希望:

  • 未来产品要出海,要支持 i18N
  • 配置通知文案的工作会交给产品策划,需要有一个统一的地方让产品同学操作,还要提供 SOP
  • 除了支持发送站内通知、邮件外,还需要对接 APP 推送,而且我们还上架了钉钉、飞书、企业微信的应用市场,需要对接这些渠道的通知
  • 除了发送用户通知,通知系统还可能用于内部推送,比如用户订阅快到期了,需要发送消息给相应的销售跟进
  • ……

这时可能你已经有点懵圈了,但作为一名产品经理,相信你很快就会意识到,你应该首先确定这个系统的利益相关者。

利益相关者

在产品领域中,利益相关者(Stakeholder)是指对产品的决策和活动施加影响或可能受产品的决策和活动影响的所有个人、群体和组织。

因为通知系统是一个公共模块,很多人都会用到,所以小明在脑海中快速思考了一下谁会是通知系统的利益相关者:

  • 需要查看和处理通知的产品使用者
  • 负责开发和维护通知系统的研发
  • 实现其他功能时需要复用通知系统的研发
  • 需要编写通知文案的产品策划
  • 需要发送营销通知的产品运营
  • 需要了解用户付费情况的销售
  • 需要测试通知的质量工程师
  • ……

只是简单脑暴一下,就有这么多利益相关者,看来这事情没那么简单啊!

场景分析

场景分析属于产品经理的基本功,一个完整的场景通常需要描述谁在什么时候遇到了什么问题,感受如何,希望怎么解决等,在这个过程中,产品经理需要尽可能地对利益相关者进行调研,了解他们的故事,才能保证最后的产出能够满足他们的需求。

因为接下来描述的场景,主要来源于我之前的工作,为了方便大家理解,在这里也简单介绍一下前公司的产品 vika维格表:它的界面长得像 Excel,是一个表格形态的产品,但不同的是,它限定了每一列的列类型,比如文本、数字、日期、单多选等,所以它本质上是一个关系型数据库。 img

在此基础上我们做了多种数据视图,比如日历视图、架构视图、看板视图,赋予数据不同的展示形式,再搭配消息通知、自动化、BI 图表等能力,用户可以自由地搭建自己的客户管理、OKR管理、项目管理、产研管理等系统。 img

因为用户会利用我们的产品打造他们的内部工作系统,所以会涉及到非常多的通知场景,比如用户可以在评论中提及其他人,对方会收到通知;还有在日期列里可以设置到期提醒,到期时会收到通知;关注某条记录,记录被修改时会收到通知。而且因为我们上架了钉钉、飞书、企业微信的应用市场,所以用户在 IM 工具里也会收到我们的通知。

note
  • 以下描述的场景为了大家的阅读体验,并没有完全列举,且进行了部分简化。
  • 前公司的工作流程相对极客,比如产品同学可以直接操作研发配置表、运营同学需调用 API 接口发送活动通知,所以本文基本不涉及操作图形界面的场景与需求,但理论上这不影响通知系统需要提供的基础能力。

普通用户

  • 小红是一名项目经理,她在注册/登录维格表时,需要接收手机/邮件验证码
  • 小红绑定了多个通知渠道(站内、邮箱、钉钉等)后,一个消息多个渠道都会收到,而且有些官方的活动通知她也不关心,她想,能不能让我自定义设置接收通知的类型和渠道呢?
  • 小明连续在 10 条记录里提及了小红,小红一下子被 10 个通知轰炸,她都无语了
  • 小红是管理员,她每天都会收到很多通知,每次清理通知中心一个一个点开实在太麻烦了,她想,就没有一键清理的入口吗?
  • 小红通知中心里面的消息太多了,她想,我怎么能找到我关心的通知呢,能不能做一个标签页分类,例如多一个分类叫“@我的”,我只要点开这个分类,就知道有多少个事项需要我处理的了
  • Amy 是美国人,在中国的外企工作,公司用维格表进行项目管理,但她看不懂中文
  • 小红用维格表做合同管理,她把合同的到期时间录入表格,希望在到期前 1 个月能提醒负责的销售续签合同
  • 小红在维格社区里提了一个问题,过了两三个月,她登录维格社区的时候,发现工作人员回复了她,她很疑惑,为什么当时她没有在维格表的通知中心收到这条通知

产品策划

  • Emma 是一名产品策划,他在策划功能的时候,需要给用户发送通知,但他不知道怎么配置,只能找到负责通知系统的小明了解怎么配置
  • 公司准备把维格表换个名字,在海外上线一个同样的产品,要求复用现有的通知系统,但是很多通知模板里都使用了维格表的品牌名和 LOGO,要怎么处理呢
  • 维格表即将上线 APP,需要支持 APP 推送

产品运营

  • 小鸣是一名产品运营,他每个月都会给开通了 APIToken 的用户推送邮件《开发者快报》。但是每次编写邮件和测试时,都要找前端研发写 HTML 界面,反复沟通看效果,很不方便
  • 研发同学听取了小鸣的建议,使用维格表配置邮件模板,小鸣可以很方便地进行邮件的撰写和测试。但要进行推送的时候,小鸣还得找到服务端研发帮忙来进行腾讯云的推送……
  • 小鸣已经推送两期《开发者快报》了,他发现腾讯云邮件推送服务有个弊端,就是没法按邮件“发信模板”进行单独的数据分析,各种数据混杂在一起。小鸣再次陷入苦恼,我该怎么持续优化邮件的转化率啊
  • 双十一活动将于下周一开始,小鸣已经编辑好了通知内容,他希望活动通知可以在下周一中午 12 点准时发送给用户

研发

  • 小罗作为一位服务端工程师,经常会收到来自其他同事的协助请求,需要处理一些不在规划以内的临时任务。小罗内心很纠结:其他同事就不能自己学习一下,然后自己操作群发吗?
  • 经常有用户反馈说没收到通知,但是我们之前没有记录通知日志,经常需要花很多时间 debug
  • 用户量越来越多,发送的通知数量也会越来越大,如何保证送达率和时效?
  • 如果一个用户 A 正在获取验证码,而运营同时给全体几十万用户发送营销邮件,怎么保证 A 能及时收到邮件?

测试

  • 小白是刚入职没多久的测试,某天接到一个任务,需要对所有通知进行一次回归测试。小白翻遍了所有能找到的PRD文档,东拼西凑找到了一些资料,但内心很崩溃:“维格表到底有多少业务消息模板呀!!还有没有遗漏的呀,有没有一份文档或者表格能全部讲清楚呀!!
  • 小白终于梳理清楚了有多少通知,但是他发现全都要人工测试,他再次崩溃了:我这一天光测这个就够够的了,其他事情都不用做了

销售

  • 有一个用户刚买了半年的订阅,能不能在到期前一个月通知我,让我 push 他续费?

提炼需求

功能性需求

一个系统通常涉及多个参与者和利益方,场景也比较散乱,为了方便理解,我们可以先梳理业务流程: img

再从业务流程中,初步提炼出需求: img

当然,除了图里列的这些,还有贯穿每个环节的数据埋点和统计需求。

非功能性需求

tip

非功能性需求,是指软件产品为满足用户业务需求而必须具有且除功能需求以外的特性,包括安全性、可靠性、互操作性、健壮性等。

基于一些边界场景,通知系统应该还具备以下这些特性,才能保证它能被长期稳定地使用:

Scalability(可扩展性):易于扩展,可满足日后的大用户量场景
Availability(可用性):尽量避免单点故障导致的流程阻塞
Highly Performant(高性能):低延迟(尤其是接收验证码类的场景)
Reliability(可靠的):丢信率低,最好保证每个通知至少能收到一次
Traceability(可追溯性):记录日志,可以追溯生产、发送、消费通知的全过程
pluggability(可插拔性):通知系统是一个公共的模块,它只处理通知的生产、发送、消费的过程,其他功能的业务逻辑应该独立于通知系统之外
……

确定目标

任何一个产品/系统,都可能存在许多利益相关者,他们会提出各种各样的需求,要满足所有的需求,几乎是不可能的。所以我们理论上需要从需求中清晰地划分出一个子集,并把它们转化为我们系统的目标。

tip

需求和目标是两个不同的概念,目标是架构师所做的决策,是产品计划完成的事情,而需求则是对受益者很重要的事情。

而且在实际工作中,因为资源有限,我们往往还需要跟研发一起讨论,梳理不同需求点间的依赖关系,利用敏捷迭代思维把目标分解成几个小目标,分阶段实现。

但因为本文主要的目的是展现一个相对完善的高可用的通知系统是怎么设计的,所以我们在这不考虑优先级的情况,假定实现以上所列的功能性和非功能性需求,就算是完成系统目标了。

实践篇

确定系统及其形式与功能

tip

系统同时具备形式与功能这两个特征。形式说的是系统是什么,而功能说的是系统能做什么。

如果我们要描述通知系统,那么它的形式是由相关的数据、逻辑、界面组成的通知传达处理系统。所以它包含用户操作界面(站内通知中心、个人设置)、研发编写的系统逻辑代码以及数据库里的相关数据。

而它的功能是到达指定的发送时间时,组装通知内容,并发送给对应的接收者。

从通知系统的定义和上面列的一些场景,我们可以发现,从服务端的角度来看,通知系统对外展现的应该是一个标准发送通知接口(实际上系统都是通过接口对外联系的),它不处理其他功能的业务逻辑。

举个例子,小明有一个早上 10 点的会议,他设置了提前 15 分钟提醒,那么通知系统是无需计算什么时候要发送通知的,而是由日程模块计算好发送时间,调用通知系统的接口时传入参数即可。

确定系统的形式与功能的好处是确定了系统的边界,这样可以降低系统之间的耦合度,只要一个系统对外的接口是简洁优雅的,即使内部如何混乱,都不会影响到外界,相当于把混乱的逻辑约束到小范围内,出错的概率大大降低。而且这样也实现了系统的可插拔,便于被其他功能/产品调用。

确定系统内部的实体

当我们确定了系统的边界以后,就要开始关注系统内部了。

tip

系统是由实体组成的,实际问题中客观存在的并且可以相互区别的事物或者概念称为实体,可以具体到人、对象、概念、事件。

我们需要定义系统内部的实体,才能进一步规划系统内部该如何运作,这部分主要考验我们对业务的理解有多深。

在此我们把通知系统的实体定义如下:

中文英文说明
通知行为Notification Action需要发送通知的行为,eg:用户关注的记录被修改后,需要发送通知
通知事件Notification Event描述发生某个行为后,谁给谁发送通知这一过程,eg:A在表格里提及B,B收到了通知。
通知渠道Notification Channel接收者在哪里收到通知,比如短信、邮箱等
通知Notification通知事件的实例,通知内容的载体
通知模板Notification Template针对不同的通知事件、通知渠道撰写的文案模板
设备Device接收通知的设备,主要用于 APP 推送

确定实体关系

tip

两个实体之间的关系表示这两个实体以某种方式相互关联。

同样地,设计实体关系也是取决于我们希望支持什么样的场景。

info

举一个典型的例子,之前企业微信上线了一个创新性的功能,就是企业之间可以组成上下游,上下游之间可以共享应用,这样的功能方便了大型集团,他们可能不同的子公司采取了组织架构隔离,但又有协同工作的需要,这样的功能可以让他们共同使用同一个应用,无需重复付费,而且使用应用的用户多了,企业付费的意愿就更强了。

当时企业微信也希望服务商们能支持这个功能,支持上下游企业共同使用应用,但我们在对接的过程中,发现了一个硬伤,就是某个企业被共享应用了以后,它就没办法再另外安装应用了,相当于如果一个供应商分享了一个项目管理应用,给它下游的分销商企业,用作上下游间的项目对接,分销商企业没办法再另外安装一个同样的应用,用作内部的项目管理。当我们咨询官方工作人员的时候,他们表示确实存在这样的场景,但是架构不支持,目前还在想办法处理。当时我的想法是,企微可能还没想清楚这个功能要怎么做,为了避免踩坑,所以暂时也不支持相关功能。

我猜想,问题可能出在,原本设计同一个应用一个企业只能安装一次,在做上下游的功能时,忽略了被分享应用的企业还有重复安装应用的场景,没有对这部分的逻辑进行处理,所以导致最终的实现稍微有些不合理,想要修改也比较麻烦。

而对于服务商来说,如果是通用性较强的产品,可能就会跟我们面临相同的问题。

我们可以使用 E-R图(Entity Relationship Diagram)来描述实体关系。

tip

E-R图(Entity Relationship Diagram)即实体联系图,也称实体关系图,是指提供了表示实体型、属性和联系的方法,用来描述现实世界的概念模型。

通知系统的 E-R图如下,注意这里的属性仅为示意,并未完全列举。 img

根据 E-R图,我们可以梳理得出数据模型: img

串联与整合

确定实体关系后,我们就可以尝试描述系统雏形,通知系统实际上只处理两个问题——通知发往哪里和发什么。 img

这时其实通知系统的主流程已经跑通了,但要打造一个高可用的系统,还需要考虑场景分析中提到的一些场景:

  • 优先级高的通知,需要保障发送时效
  • 用户量增大时能够轻易扩展
  • 发送失败后需要重新发送
  • 对全流程进行数据统计,便于优化推送策略

根据这些场景,我们来增加亿点点细节: img

同时我们可以定义一个通知的状态变化如下: img

至此,通知系统的架构就完成了,回顾我们在战略篇里列的场景和需求,尽管有些需求并没有体现在这个架构中,但不难看出,后续都是可以支持的:

  • 用户侧:分类展示和处理通知、用户个性化设置通知渠道和类型等
  • 研发侧:可以根据日志部分快速定位漏洞,易于维护
  • 产品侧:整个系统是可插拔的,可以对接其他功能/系统/产品;可以形成完整的配置 SOP与业务说明文档
  • 运营侧:无需通过研发和操作界面也可以自己发送运营通知;可以发送内部通知

而这些就是一个良好架构系统的魅力——它能自我进化,涌现出更多的可能性。

结语

这是我写的第一篇产品相关的文章,一共花了十多天的时间整理、学习和输出,但其实这背后更多的是在前公司里长达几个月断断续续的团队调研与讨论,在此也非常感谢前公司的小伙伴们的支持与帮助~~

耐心读到这的朋友,可能你也发现了,理解并设计一个复杂系统,并不是纯粹的「技术」活,而是我们熟悉的产品思维。

记得我在第一次接触系统架构相关知识的时候,是看了一本书《企业IT架构转型之道:阿里巴巴中台战略思想与架构实战》,这本书主要讲的是阿里巴巴在业务发展过程中,遇到了什么问题,以及如何优化系统架构的。

这本书中有很多我并不能完全读懂的技术知识,问题的范围不同,但架构师解决问题的思路跟产品经理是类似的,无非也是「了解场景 > 分析需求 > 设计方案」。

可以看到,所有的架构设计、功能设计都是源于场景,而这也是为什么我花了很长的篇幅来描写用户场景。

虽然通知系统作为一个基础功能,在不同形态的产品中差别不大,但最终本文给出的解决方案必然依赖于给出的假定场景,大家可以需要根据自己的实际需求进行修改或增减。

正如康威定律所说的:“设计系统的架构受制于产生这些设计的组织的沟通结构。”

系统架构必然是其利益相关者沟通结构的缩影。

参考资料

系统设计(四) Design Notification System
《系统架构:复杂系统的产品设计与开发》
消息通知系统设计 消息通知系统模型设计