项目的难点和挑战是什么?

在线教育平台,后端有一个Studio服务给老师创建课程用的,有一个Notifications服务用于通知。

老师帮助学员创建账户并帮他帮忙一个隐藏的课程,账户创建成功并报名需要给学员邮箱发送报名成功的邮件,邮件包含账户和密码和课程链接。

这个需求的难点是需要原子性和一致性。

Studio服务创建学员账户并报名,并产生发送邮件这个事件,写入数据库和发送邮件应该是原子的方式运行。

当微服务在数据库更新后发送事件通知时,这两个操作应以原子方式运行,以确保数据的一致性和可靠性。

如果数据库写入成功但事件通知失败,则通知服务将不会意识,则学员收不到邮件而系统产生了垃圾账户。如果数据库写入失败但发送了事件通知,则学员无法根据邮件内的账户登录。

首先想到的是使用异步事件驱动通信,写入成功之后向消息队列发送事件,数据库操作失败直接不发送消息,消失失败则数据库回滚,表面上看起来天衣无缝了。

但是比如说网络IO问题和服务器宕机的问题,使得消息投递成功了但没有通知到Studio服务,Studio服务认为消息投递失败,则回滚数据,实际上消息已经被消费了。

之后为了解决这个问题,就采用了事务收发箱模式。事务发件箱模式解决了分布式系统中当单个操作同时涉及数据库写入操作和消息或事件通知时出现的双重写入操作问题。

创建一个新表,发件箱表outbox,用于存储需要发送到消息代理的事件。在同一事务内,执行创建学员账户、报名课程、插入邮件事件到发件箱表这三个操作。另写一个服务(发件箱事件处理服务)从发件箱表中读取并将事件发送到消息队列,并从发件箱表删除事件。

另外还有一个补偿机制,老师可以一键点击发送邮件,后端会检查发件箱发送邮件。

过往所作项目的难点?

在线教育平台,老师在平台创建课程,上传视频课件,需要实现视频转码并点播的功能。平台需要对接两个外部服务,OBS对象存储服务和VOD点播服务。流程是这样的,前端页面调用OBS的SDK上传视频到桶,返回bucket路径和资源ID,POST到后端。后端存储资源ID。

难点在于VOD和OBS之间需要同步时间、视频大小有不同的转码时间,某些帧率的视频有转码的失败的可能,转码失败的视频重新转码可能会成功。

通过任务队列做后台作业,一些补偿机制进行重试。

比如 MySQL 优化,真正用心思考与实践过的人,绝对不会简单的答出查询语句、表结构、索引之类的优化就就结束了。他会结合自己的思考谈自己的经历。为什么这个 SQL 有问题,我是怎么找出它的,在这个过程中,我走过那些无用功,才最终找到自己的答案。