一个应用被称为数据密集性的(Data-Intensive applications),如果数据是其主要挑战(数据量,数据复杂度,数据变化速度),与之相对的是计算密集型,即处理器速度是其瓶颈。现今很多数据都是数据密集型的,而非计算密集型,CPU很少成为瓶颈。这是我们讨论这个问题的价值。
数据密集型应用通常同许多标准组件构成,如:
- 数据库
- 缓存
- 索引
- 流处理
- 批处理
如果你觉得这些玩意听上去平淡无奇,那是因为这些都是非常成功的抽象,以致于让人不假思索并习以为常,就像生活中水和空气一样,没什么神奇的。但现实并没有这么简单!因为你很快就会懵逼了,就像我一样。
关于数据系统的思考:
我们通常认为,数据库、消息队列、缓存等工具有显著区别,但其实界限越来越模糊,例如数据存储可以当成消息队列使用(Redis),消息队列也可以持久存储(Kafka)。
其次单一工具无法满足所有的数据处理和存储需求,总体工作被拆分成一系列能被单个工具高效完成的任务,并由应用代码将它们串联起来。比如缓存和全文搜索功能(ES)从主数据库剥离,应用代码负责同步。下图是这种架构可能的样子。

我们把这个架构封装起来,提供外部一致的体验,当然这里面会有很多坑。比如:如何保证正确性和一致性?部分组件不可用降级时如何保证客户体验良好,性能不受影响?如何扩容?什么样的API是好的API?
重点讨论了三个最重要的问题的定义:
- 可靠性
系统在故障时(硬件故障、软件故障、人为错误)仍可正常工作。 - 可扩展性
有合理的方法应对系统增长(数据量、流量、复杂性)。
讨论X可扩展,Y不可扩展是没有意义的,讨论可扩展性意味着如果系统以特定方式增长,有什么方式可以持续应对增加的负载?性能参数变现如何?(如中位线,99%线,SLA保证) - 可维护性
工程师,运维人员在不同的生命周期,都能高效工作。
比如在可靠性时,提到云平台的设计优先考虑的是灵活性和弹性,而不是单机可靠性,所以应用程序必须能容忍;
在可扩展性时,提到系统今天能可靠运行不代表明天能可靠运行,服务降级的一个常见原因就是负载增大,而负载增大并不只是扇入(来源)问题,而是扇出(后续)问题。如微博的挑战可能不在于大量的针对发表微博的存储,而是让微博显示在关注者列表上的问题,运单的问题不仅在可见的运单线性增长的问题,而是后续运单处理的问题;
在可维护性时提到良好监控、可视化、自动化的重要性及铁打的营盘流水的兵,要维持组织对系统的了解,代码抽象减少问题额外复杂度的重要性,什么叫额外复杂度:由具体实现中涌现的,而非从用户视角产生的。
从0开始的大型架构基本是失败的,架构都是演进的。关于扇出的复杂性提一个简单的例子:发一条微博,存储结束后,从技术上微博是如何出现在关注者时间线上的?
一种是拉模式,用户请求时示意如下:

一种是推模式,示意如下:

如何取舍?
我们都知道不幸的是,使应用可靠,可扩展,可维护并不容易,所以我们后续一起慢慢探索吧。
网友评论