对软件系统的一些理解

前言

这篇文章是想表达我对系统软件的一些理解,风格跟之前的不太一样,整体偏“务虚”。我自己其实是不太擅长“务虚”的,甚至是有点排斥。就跟相比起看论文,我更喜欢看code,当然我也看论文,只不过相对来说少些。

毕业以来一直在数据库存储引擎领域工作,过去5年主要精力集中在阿里自研LSM-Tree存储引擎X-Engine研发上,并且在过去两年多时间我们完成了X-Engine的云原生架构升级和商业化,在公有云上承接一定规模的客户并稳定运行,在业界应该也是首个基于LSM-Tree架构实现云原生能力的TP存储引擎。完整经历一个TP存储引擎的架构规划、设计研发、落地上线,稳定性运维的全周期,并且得益于从我进入数据库领域一路以来经历的高水平团队、technology leader以及整个团队成员的出色工程能力和技术视野,加上我自己在此过程中的一些思考,阶段性的形成了一些自己的心得体会。

另外,跟业界一些优秀的架构师和工程师交流,发现对于系统工程的理解有很多的共鸣,也收到很多非常有价值的输入,当然也存在一些不同的观点。这也是促使我写这篇文章的主要原因,希望能将我自己的一些理解表达清楚,这些观点并不fashion,更谈不上创新,更多的是一些自己的思考和经验之谈。

对系统软件的看法

观点1:软件的本质是对硬件资源的消耗。不同软件的区别在于,消耗硬件资源去解决什么问题以及如何分配硬件资源的消耗。软件架构设计中经常提到"抽象"和“trade-off”,抽象本质上的就是"解决什么问题","trade-off"其实就是"如何分配硬件资源"。

举个例子TP存储引擎和AP存储引擎,从实现上可以列举出一大堆不同的地方,行存 VS 列存、二级索引 VS ZoneMap索引、强事务 VS 弱事务等等。这些不同之处其实都是结果,导致这些的根本原因是:

1)两者解决的问题不同,TP场景主要是online实时业务,这些业务的特征是整体数据规模相对较小(真正需要online处理的数据,历史数据可能很多)、请求短平快、数据locality明显、高并发低时延等,而AP场景整体的数据规模大、计算密度高、高吞吐等。(解决什么问题)

2)TP引擎的完整事务支持使得业务的并发控制简化很多,其实就是把业务系统本来需要做的事情,TP引擎自己做了,当然也就意味着TP引擎需要为此消耗一部分硬件资源。而AP引擎为了加快数据入库的速度,事务的支持比较弱,这部分工作还是由业务系统来完成(比如ETL),也就不需要为此消耗硬件资源。(如何分配硬件资源)

观点2: 系统软件的重大变革,背后基本都是硬件发展所推动的。这跟观点1)是相呼应的,系统软件领域的理论在进入21世纪之前,学术界已经做了广泛深入的研究。从最开始计算机的出现,到大型机和小型机,再到家庭PC和廉价通用服务器,以及现在的云计算IAAS服务,基本上系统软件发展也是跟随这个脉络在发展。系统软件的再次火热,本质上也是因为IAAS这个“新硬件”所推动的。整个IAAS的on-demand获取,打破了系统软件之前在物理资源受限的背景下很多设计,这也就是为什么云原生系统软件会迎来新的机会。

观点3: 几乎不存在某一种系统架构全面领先另外一种架构。这跟观点1)2)是相呼应的,不同的架构选择背后都是不同的trade-off,所谓有得必有舍。经常听到一些说法,你看这篇论文、这篇文章,他们这种架构就没有某问题,我们这种架构就有这个问题。我听到这些观点的第一反应是质疑,这里边主要有三个原因:

1)很多论文和文章的实验结果是没法复现的,也就说很有可能他的结论就有问题;

2)很多时候只会强调“得”的部分,而“舍”的部分是没有讲的。

3)我们系统所存在的问题到底影响有多大,是不是可以解决的,这些需要量化的数据才能确定。轻易地被各种论文和文章的结论影响,很有可能会做出一个不伦不类的系统。就像习武之人各个门派的武功都学学,最终很容易走火入魔。

观点4:条条大路通罗马,最终系统对外呈现的区别,更多的是工程实现的原因,而非架构的原因。不同的系统架构需要解决的大部分问题本质上其实是一样的,并且组成一个系统的零部件都差不多,只是根据需要选择哪些零部件来构建系统。只有躬身入局,真正地去面对问题、分析问题、解决问题,才能认清楚其中的本质,否则很容易变成纸上谈兵。

举个例子:经常有人问我LSM-Tree架构中持续写入数据时,compaction问题对性能影响很大。这个问题我是这么看的,首先LSM-Tree架构上写入吞入优势的其中一个原因是,相比于innodb这种磁盘B+ Tree在写入的时候直接sort on write(page内有序,全局有序),LSM-Tree架构选择将一部分sort转移到sort on compaction、sort on read,本质上是将写入时排序的资源消耗,转移到了compaction或read。刷脏其实是包含两个动作:生成脏页,将脏页刷盘。innodb相当于是在写入的时候生成脏页,在刷脏的时候就是单纯的io操作。而compaction其实是同时做了生成“脏页”和“脏页”刷盘。innodb如果持续写入的话,也会有刷脏来不及时导致影响写入性能的问题。因为innodb刷脏和compaction之所以成为问题,本质上都是因为内存和磁盘写入速度的差异,导致生产者消费者模型失衡。所以innodb的刷脏和LSM-Tree的compaction本质上是相同的问题,只是通过不同的方法来将这个过程对系统的影响降到最低。

系统软件构建的七个面向

接下来的内容,主要是在进行详细设计的时候我认为比较重要的原则。这些原则的道理其实很容易理解,并且“软件工程”这门学科已经研究的很充分,但是实际操作的时候其实是蛮困难的,可能是历史包袱的原因,也有可能是外界环境的原因,需要根据实际情况做出不同的trade-off。值得注意的是,我们做出的trade-off一定是要经过仔细考虑的,而不是草率的,否则很容易出现“有舍没有得”。另外遵守这些原则设计实现出来的系统和不完全遵守这些原则设计实现出来的系统,结果其实是“好和更好的区别”,但是“好多少”这个量在系统做出来之前,其实很难衡量。这七个原则不是独立存在的,而是相辅相成的。

面向场景: 首先我们需要明确要解决什么问题,这是整个系统构建的出发点。one size fit all的系统在过去是不存在的,在未来也不一定存在。系统的完善,必然是要靠不断的迭代来完成的,那么如何迭代本质上就是我们在那些阶段解决哪些问题。一个系统可以有远大的目标去解决很多问题,但是所有问题的路标需要有相对清晰的规划,以达到既可以快速满足需求,同时保留向未来演进和扩展的基础。

实际研发过程中,可能发生的两类错误是:

1)想采用敏捷开发的方式来进行工程管理,以满足整个迭代的需求。敏捷开发本质上先定义最小功能集,也就是首先想清楚解决什么问题,然后快速的迭代扩充功能,有点像小步快走。在实操上,很容易把敏捷开发搞成了"快、糙、猛",有点大干30天赶英超美的味道。

2)问题定义不清楚,系统的“不变式”设置就容易草率。每个系统都有一些“不变式”,随后很多设计都是基于这些不变式进行展开的,比如在LSM-Tree系统中一个常见的“不变式”是更新版本的数据在更低的层次,同一行的数据的多个版本如果同时在memtable、level0、level1中存在,那么必然memtable中对应的版本是最新的,level0中的版本也比level1中的更新。如果在迭代的过程中发现之前设置的“不变式”不合理的,那么进行改动的代价是非常之大的。

面向解耦:无论是自上而下的去设计系统,还是自下而上的去设计系统,很重要的一个思考逻辑就是将各个模块间的耦合度降到最低。解耦做地比较好的系统,往往意味着:

1)每个模块的功能是考虑的比较清楚,方案的完整度是比较高的;

2)有利于专注的将某个模块实现的更加高效,避免其他模块的影响;

3)有利于之后的迭代,影响面可控;

4)出了问题好排查,单个模块的问题是比较好排查,真正那些难搞的问题往往是问题在各个模块间传导后才暴露出来,比如A模块出问题,经过模块B、C、D,最后在模块E暴露出来。

有些质疑的观点会说,面向解耦的思路去设计,有可能会牺牲系统的整体性能。其实这个跟不要一开始就为性能做过度的设计是一样的道理,真到了某些解耦的设计影响了性能,那么该耦合的就去耦合。把两个模块耦合在一起的难度往往是低于把耦合在一起的两个模块拆开。

面向防御:这个就是防御性编程的逻辑,要假设调用的函数都是有可能出错的, ,比如内存分配可能出错,io可能出错,基础库的调用可能出错等等,基于此来考虑如果出错,系统的行为是什么。有一个非常简单的原则就是"fail stop", 如果没有完整的防御,那么即使fail了也很难立即stop,最终造成一些很奇怪的表象。

通常的质疑是:

1)你看这个函数的逻辑肯定不会失败的。也许从当前来看这个函数确实不会失败,但是很难保证随着迭代增加逻辑,之后没有失败的可能性。

2)加了这么多防御,防御代码比实际逻辑的代码还多,会影响性能。首先,现在cpu的分支预测能力,基本上可以做到绝大部分情况下防御代码不会影响性能。另外跟对于面向耦合的质疑一样,真到某些防御代码成为了性能瓶颈,该优化就优化。优化一个防御,总比去解决一个因为没有防御而导致的问题代价更低吧。

面向测试:在测试阶段修复问题的代价是远低于在生产环境修复问题的代价,因此让系统变得可测试是非常重要的。系统可测试的标准就是,能方便的进行单元测试、集成测试,并覆盖绝大部分的代码路径。可测试的系统,随着不断的迭代,会累积越来越多的测试case,不断的夯实稳定性基础。面向测试跟面向解耦、面向防御是相辅相成的。只有模块间耦合度足够的低,才有可能做更多的测试,否则做一个模块的测试需要mock很多乱七八糟的东西。面向防御会使得测试的行为可以更好的预期,不然输入了一个异常的参数,具体怎么失败是不确定的,那测试case就很难写了。

面向运维:bug是一定会有的,对于复杂的系统,不管前期做多少准备都很难避免生产环境中遇到未知的问题。面向运维的主要目的是,遇到问题的时候,能用代价最低的手段去及时止损。遇到线上问题,动态调参数就能解决比需要重启才能解决的代价更低,重启能解决比需要发版才能解决的代价更低。面向运维不仅仅是加几个参数,加几个开关那么简单,而是需要把“面向运维”作为设计方案的重要组成部分来考虑,保证出了问题有运维手段,有运维手段敢用,用了以后有效果。

面向问题本质:当去解决一个问题的时候,一定要多思考这个问题的本质原因是什么,简单的问题复杂化和复杂的问题简单化,都是因为没有抓住本质。如果能思考清楚其背后的本质原因,从源头避免掉是更加彻底的解决方式,否则很容易陷入不断打补丁的状态,我一直有个观点:“没有抓住问题本质去解决问题,结果往往是在制造问题”。另外一个经验是,如果一个模块连续出了好几次问题,那么就要想想是不是在最开始的设计上就有需要改进的地方。

面向可视化:可视化的目标主要是以更加直观的形式,来展现系统运行状况,这对于系统调优和诊断是非常重要的。当系统异常时,可视化的方式可以帮助快速定位到系统哪里出了问题。另外一方面是,可以提供接口给监控系统做历史状态的追踪。比如oracle的诊断监控就是一个非常优秀的案例,而SnowFlake对于内部状态的打点监控也是近乎疯狂。

总结

说了这么多,最终系统还是靠一行行的code实现出来的,保持匠心、严谨、较真的态度去打造系统是非常朴素正确,但又很难做到的事情,共勉!

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/510624.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

InnoDB 之 UNDO LOG 介绍

undo log的组织形式 此部分是关于Undo log的组织形式的一个介绍;主要分为两部分来对undo log的组织形式进行介绍:文件结构和内存结构。在介绍这两部分时,先从局部出发,最后再给出各个部分的联系。 1. 文件结构 首先&#xff0c…

Spark 如何对源端数据做切分?

引言 典型的Spark作业读取位于OSS的Parquet外表时,源端的并发度(task/partition)如何确定?特别是在做TPCH测试时有一些疑问,如源端扫描文件的并发度是如何确定的?是否一个parquet文件对应一个partition&am…

数据库事务隔离发展历史

事务隔离是数据库系统设计中根本的组成部分,本文主要从标准层面来讨论隔离级别的发展历史,首先明确隔离级别划分的目标;之后概述其否定之否定的发展历程;进而引出 Adya给出的比较合理的隔离级别定义,最终总结隔离标准一…

为什么游戏行业喜欢用PolarDB

为什么游戏行业喜欢用PolarDB 游戏行业痛点 在我看来, 不同行业对数据库使用有巨大的差别. 比如游戏行业没有复杂的事务交易场景, 他有一个非常大的blob 字段用于存储角色的装备信息, 那么大Blob 字段的更新就会成为数据库的瓶颈, 比如在线教育行业需要有抢课的需求, 因此会有…

从业务开发中学习和理解架构设计

前言 在软件开发领域经常会接触到架构这个词汇,在我最初的印象中,架构是一个很高级的词汇。它似乎代表了复杂的工程结构、高层次的抽象设计、最新的开发语言特性等等。对于当时只专注于写业务逻辑的我来说,不免心生对架构的敬畏。工作中对架…

腾讯云联合中国联通打造下一代IDC数字化运营应用

近日,腾讯云联合中国联通智网创新中心打造的下一代IDC数字化运营应用,正式亮相2022中国联通合作伙伴大会。立足双方资源和经验优势,该数字化应用可实现对数据中心电力系统、制冷环境、安全防范等全方位智慧化运营,助力中国联通推进…

研发效能的思考总结

前言 在谈效能之前,我想先谈谈作为一个技术人或者技术TL,研发的核心价值是什么? 之前看了一篇文章,比较有意思,分享一下观念: T外包公司:最核心的竞争力不是技术,而是快速响应、资…

以“升舱”之名,谈谈云原生数据仓库 AnalyticDB 的核心技术

背景 说到升舱,我们首先想到的是飞机经济舱升级到商务舱、头等舱。阿里云企业级云原生数据仓库AnalyticDB(以下简称ADB)[1]在帮助以金融机构为主的行业数字化转型和传统数仓升级项目中,也引用了“升舱(仓)…

阿里云联合平行云推出云XR平台,支持沉浸式体验应用快速落地

近日,阿里云与平行云联合发布云XR平台,降低云端视觉计算应用的开发门槛,加速数字孪生、虚拟人、虚拟现实、沉浸式体验与虚拟仿真平台等XR应用落地,帮助互联网、新零售、社交、工业、交通、城市管理等行业探索创新业务形态。 阿里…

放弃笨重的 IDE,转而尝试 Emacs

【编者按】IDE对于开发者而言,重要性不言而喻,但随着功能愈发强大,它们对硬件的要求也日益提高,甚至越好用的 IDE 就越笨重。链接:https://renato.athaydes.com/posts/switching-from-heavyweight-ides-to-emacs.html声…

“穿越”到虚拟世界笑风生,网易瑶台沉浸式活动平台创新云端活动体验

2020年,第二届分布式人工智能国际会议(DAI 2020)因疫情的到来险些无法举办,南京大学人工智能学院的俞扬老师通过与网易伏羲团队的合作,最终在网易旗舰级武侠端游《逆水寒》中顺利举行了本次会议。300余位全球人工智能领…

云上解锁Web3.0 阿里云XR平台助力彼真科技呈现沉浸式演唱会

摘要:通过将沉浸式演唱会应用托管到云XR平台上,彼真科技也无需像传统应用一样做大量的终端适配工作,通过Web协议即可将虚拟演唱会《故障四方》的国风科幻世界呈现在不同的终端上。云XR平台完成了算力调度、渲染、推流、编码和用户管理等工作&…

这种精度高,消耗资源少的大模型稀疏训练方法被阿里云科学家找到了!

近日,阿里云机器学习PAI关于大模型稀疏训练的论文《Parameter-Efficient Sparsity for Large Language Models Fine-Tuning》被人工智能顶会IJCAI 2022接收。 论文提出了一种参数高效的稀疏训练算法PST,通过分析权重的重要性指标,得出了其拥有…

兼顾时尚与商务? ThinkPad Z 重新定义“商务本”

因为疫情等不确定因素,在过去三年中,混合办公模式已经成为职场的新常态。新一代工作族的商务办公笔记本不仅要随身携带完成日常工作,一些人还可能“身兼数职”,在工作之余也需要笔记本的配合。办公室里严谨、内敛商务本设计&#…

Go原生插件使用问题全解析

导言 本人在设计和落地基于Go原生插件机制的扩展开发产品时踩到了很多坑,由于这方面相关资料很少,因而借此机会做一个非常粗浅的总结,希望能对大家有所帮助。 本文只说问题和解决方案,不读代码。 一些背景知识 2.1 运行时 通…

从云计算到函数计算

从云计算到函数计算 函数计算,你的名字 云计算,是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需求提供给计算机各种终端和其他设备,使用服务商提供的电脑基建作计算资源,因此用…

基于 OPLG 从 0 到 1 构建统一可观测平台实践

应用架构与可观测技术演进历程 在软件开发早期,单体应用架构因其结构简单,便于测试和部署,得到了广泛的应用,对应的监控诊断技术主要是基于日志和日志关键词的指标监控。随着软件复杂度的不断提升,单体应用架构逐步向分…

从运维到运维大神,只需要一个正确的选择

马上就是7月24日了,听群里的朋友说,7和24这两个数字是运维工作的最佳体现——7X24小时待命,所以咱们IT人将这一天自定义为“运维日”。 对于运维工作来说,想要在黑天鹅横飞,灰犀牛直撞的当下,既能独善其身…

主流定时任务解决方案全横评

定时任务作为一种按照约定时间执行预期逻辑的通用模式,在企业级开发中承载着丰富的业务场景,诸如后台定时同步数据生成报表,定时清理磁盘日志文件,定时扫描超时订单进行补偿回调等。 程序开发人员在定时任务领域有着诸多框架和方…

基于阿里云 Serverless 函数计算开发的疫情数据统计推送机器人

一、Serverless函数计算 什么是Serverless? 在《Serverless Architectures》中对 Serverless 是这样子定义的: Serverless was first used to describe applications that significantly or fully incorporate third-party, cloud-hosted applications…