16 September 2017

这是笔者博客里第2篇关于工程开发的个人思考的文章。第1篇还是16年1月写的 《对软件开发的一点思考》,那篇文章主要站在代码质量的角度来介绍我对工程开发的认识和想法,比较偏工程细节。而这篇文章会稍微宏观些,从系统设计的角度来描述我的一点认识和想法。虽然两篇文章相隔1年半,期间我又负责了若干个新项目,有了更多的经验和教训,但有个核心观点跟那篇文章还是一样,那就是合格的算法工程师要有算法策略、工程开发和产品思维这三方面的综合能力,肯定要突出算法策略方面的能力,但工程开发也不可不重视。

虽然笔者会重视工程开发,不断从项目中总结经验教训,但是与工程开发的大拿相比,笔者的经验肯定相差甚远,所以下面可能有些观点或者描述不大正确,还请批评指正。

系统设计需要主动而且全面地考虑需求

大部分软件工程方面的书籍都会罗列出好的系统设计要考虑哪些方面的因素,比如:正确性、性能、健壮性、可扩展性、可靠性、易用性、安全性、兼容性、可移植性等等。这些专业书籍里都会详细而且全面地介绍每个因素所涵盖的内容。因素虽多,但它们不必靠死记硬背,因为大部分因素在系统设计师看来会自然而然的考虑到。写软件工程著作的作者也是从实践中提炼出那些因素,而不是凭空想出的。

在实际系统研发中,系统设计首先要确保充分理解了产品需求文档(俗称PRD),以保证后面实现的功能是符合产品需求的,这即保证了正确性。另外在正确性的同时多做些考虑,为将来可能的需求多做些准备,比如:

  • 性能是否还有提升空间
    • 能否改良算法;
    • 能否改良数据结构;
    • 能否增加缓存;
    • 能否改良硬件设备。
  • 将来是否会有更大QPS的要求
    • 如果使用多进程,那多进程的资源开销能否hold住,如果不能hold住的话,能否用上内存映射mmap技术;
    • 如果使用多线程,那各模块是否线程安全,如果线程不安全的话,是用多线程同步(加锁解锁)的技术,还是将不同的模块各自服务化,各自用比较合适的并发方式实现;
    • 是否可以增加机器,当然这是最简单粗暴的办法。
  • 将来是否会有更小latency的要求(这点与提高性能有一点重合)
    • 是否可以把一些费时的计算提前算好并缓存,用牺牲空间换时间的思路减少latency;
    • 是否可以增加机房以部署服务,使得跨机房请求转变成同机房请求,以减少服务的响应时间。

针对产品需求,系统设计师在有了初步的设计方案(可能不止一个方案)后,就需要多想一步,多做类似于上面的自问自答。没有完美的设计方案,只有适合业务场景的设计方案。软件工程常提这么一个观点:给一个框架做的修补越多,这个框架一般会越来越不稳定,更容易引入bug,也更难维护和扩展功能。在不“过度设计”的前提下,多自己质疑自己,适当考虑业务上未来可能的需求和挑战,多提问题多想解决方案,有了这些工作后,设计的系统会更健壮些,更有可扩展性。

对于如何找解决方案,这既可以从软件层面(比如改良数据结构和算法,引入多并发技术,牺牲空间换时间,牺牲时间换空间等)思考,也可以从硬件层面(比如用上缓存,用上SSD盘等)思考。

系统设计需要达到资源和需求的平衡

上面介绍的内容是系统设计的几个方面及其解决办法,是系统设计师基本可以完全把控的内容。但在实际中,系统设计师还会碰到一些自己不能完全把控的情况,也就是说在实际中,系统设计师考虑的并不只是上面的那些内容。


图1 系统研发是把输入转变成输出的过程

如图1所示,我们可以把系统研发的过程视作把输入转变成输出的过程,那系统设计则要考虑如何把输入转变成输出。输出是什么?它是一个系统,能满足产品的当前需求,也能一定程度满足未来可能的需求。那输入又是什么?它其实是为了产出这个系统所能用到的资源,资源不只包括机器资源,还包括人力资源和研发时间资源,有些时候甚至还需要用到新技术或者说用到团队所不熟悉的技术,这就是技术培训资源。资源总是有限的,有时需求要求较高,比如估算工时为3个人月,但现在团队只能配置上1人2月,这时可能砍点不那么紧急的需求会是常用的做法。所以笔者认为系统设计是要在资源和需求目标中达到一种平衡(balance)。在有限资源作为投入的情况,系统设计如何尽可能满足需求(这样一种描述就很像是数学中的优化问题,给定约束条件,求解目标函数的最优解。只不过需求是个离散的概念,不能求梯度,基于梯度的优化算法就都使不了)。

在数据挖掘项目里,系统设计则要考虑更多情况下的平衡。比如数据挖掘通常需要用到分布式计算平台,计算平台的资源经常是紧张的。为了保证服务的稳定性,这时可能会选择对计算资源要求不那么大的设计方案。再比如经常还需要在机器学习模型的复杂度和效果中做权衡,复杂模型在inference时的计算代价较大,可能会极大的影响服务的latency。为了满足服务的latency要求,这时可能会选择模型相对简单的设计方案。

总结

不同于软件工程方面的书籍从学术的角度介绍系统设计,本文从笔者的一点实际经验出发,先后总结了2个朴素观点,第一,系统设计需要主动而且全面地考虑需求;第二,系统设计需要达到资源和需求的平衡。


原创文章,转载请注明:转载自vividfree的博客

本文链接地址:对系统设计的一点思考




blog comments powered by Disqus