您的当前位置:首页正文

一张图总结架构设计的40个黄金法则

2024-11-28 来源:个人技术集锦

尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,很多小伙伴拿到非常优质的架构机会,常常找尼恩求助:

在此之前,已经有很多很多小伙伴遇到这样的难题,找尼恩来求助。

这里,尼恩借着帮助这个小伙伴的机会,给大家梳理 40条黄金架构法则,帮助大家一招制敌。

同时,把这个40条黄金架构法则,也收入咱们的 《》V160版本《架构专题》,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到文末公号【技术自由圈】取

如何抢到一个年薪100W的offer?

首先抛一个比较棘手的问题:

如何抢到一个年薪100W,管理幅度在100人以,优质架构offer?

今天上午,咱们社群一个43岁的小伙, 找到尼恩, 求助这个难题。 他正在抢夺这个岗位。

为啥叫做抢夺呢?

因为和他竞争这个岗位的, 是来自另外一个大厂的候选人, 候选人是大厂P8+, 有大厂背景背书。看上去竞争很占优势。

而咱们社群这一个43岁的小伙,没有大厂背景,这点是他的短板。

所以,叫做抢夺。

当然,咱们这个小伙伴,也有长板。

  • 第一个长板是: 他本人的人脉。 小伙为人和善,言谈举止令人很舒服, 公司高层映像好,有人推荐他。

  • 第二个长板是: 他本人的外援。 小伙伴有尼恩帮忙, 尼恩这边长时间梳理架构方案/架构套路/架构实操。 尼恩3高宇宙理论既能够上得厅堂(理论层面、宏观层面的架构能力强),也能够下得厨房(技术走地、代码落地层面的架构强), 而据说小伙伴的竞争对手,也那个大厂P8+, 在落地层面非常虚弱。

看看尼恩给小伙伴出的一个 技术架构图,就知道有点干货了:

注意:请点击图像以查看清晰的视图!

注意,这个仅仅是大系统的三分之一。 仅仅是三分之一。

毕竟,人家是年薪100W的offer。 其他的三分之二,没有办法露哈。

架构学问,也是艺术

架构师是学问,也是艺术。

架构师学问,这里架构构师至少需要掌握网络知识,硬件,软件,架构理论、架构哲学等方方面面的知识:

除此之外, 架构师在做方案的时候,有很大的发挥空间。

所以,架构师就是一位大厨, 当然,架构也是一门艺术。

回到此文,此文的目标和意义:主要是给前面说的那位小伙伴帮忙,助力的。

所以,接下来,梳理一下架构的36条黄金法则, 帮助他逐鹿100W年薪offer。

大家也可以收藏起来, 作为自己做架构的参考资料。

架构的36条黄金法则

黄金法则1:演进式法则

“一个优秀的大型互联网系统架构,不是设计出来的,而是不断演进而来的” ,

架构的演进,其本质在于技术是服务于业务需求。

业务需求是不断变化发展的,而这,天生就注定了技术架构的不断演变,是一种必然的选择。

一般来说, 演进的路线是: 单体架构-> 集群架构-> 大型中台化架构

1、单体架构

产品早期,通常是一些尝试性的产品探索/试验。

特点是: 用户少、数据量小、吞吐量小、可用性要求低。

需要的是快速验证,然后不断收集用户反馈,完善产品业务逻辑。

典型特点就是时效要求高、产品逻辑不够完善、不确定性大。

在这一阶段,对技术架构通常没有太高的要求,只需要实现基本的业务功能就行,从而技术投入自然也就不大,因此,单节点架构是比较适合的。

2、集群架构

随着业务的发展,对系统的处理能力、高可用性也就提出了越来越高的要求.

这样,系统就演进到了集群架构阶段。

在集群架构阶段,引入的技术/组件会慢慢变多,团队成员也会逐渐壮大。

3、大型中台化架构

为解决系统重复建设、能力复用性低的问题,启动了中台化建设步伐。

中台建设并非从零开始,前期已经积累了行业中多个场景的业务和技术的中台能力。因系统建设的复杂,亟需一个中台大脑站在全局视角进行公司中台能力的梳理和建设。

DDD建模流程、设计流程是 中台化架构 的绝配。 通过引入新的建模流程,完成 中台化的宏观分析和架构建模。

Tips:
在云服务厂商的支持下,集群架构已经能够支撑较大的用户流量了。云服务器、云数据库等云端基础服务的支撑能力,也比前些年要好了很多,升级扩容也方便了许多,已经足够满足一般规模下的系统性能需求了。所以,不要觉得业务量一上来,就立马要改系统架构,因为这反而可能带来不必要的麻烦。有时,直接通过升级云服务器/云数据库等的配置,就可以解决问题了。(通常来说,常规业务场景下,通过一些优化改造,顶住1万以内的QPS是没有太大问题的)。

具体请参见尼恩的《DDD学习圣经》

黄金法则2:先进性法则

使用先进的、主流的 架构方法论、架构思想、架构原则 ,去指导 项目的架构。

哲学上有一个天条:存在即合理。

先进的方法、理论、思想、原则 之所以先进, 必有某些优势的地方, 所以需要吸纳这些优势,去指导项目的架构。

比如说这几年 比较先进 的DDD架构、中台化架构等等。

具体请参见尼恩的《DDD学习圣经》

黄金法则3:高并发 法则

高并发指的是系统同时处理很多请求。

例如:淘宝的双11、春运时的抢票、微博大V的热点新闻等。

高并发架构涉及到了 很多细分领域的架构,比如 缓存架构、异步架构、链路保护架构、自伸缩架构、、分库分表架构等等。

具体请参见尼恩的《价值10W的3高架构知识图谱》

黄金法则4:高可用 法则

高可用,英文单词High Availability,缩写HA,它是分布式系统架构设计中一个重要的度量。

业界通常用多个9来衡量系统的可用性,如下表:

既然有可用率,有一定会存在不可用的情况。

不可用一般分为有计划的和无计划的,有计划的如日常维护、系统升级等,无计划的如设备故障、突发断电等。

我们对此作如下分类:

  1. 设备故障:机房断电、硬盘损坏、交换机故障。

  2. 网络故障:网络带宽拥堵、网络连接中断。

  3. 安全问题:利用系统漏洞进行网络攻击。

  4. 性能问题:CPU利用率太高、内存不足、磁盘IO过载、数据库慢SQL。

  5. 升级维护:由于业务变更或技术改进而引起的系统升级。

  6. 系统问题:分布式系统中存在服务的依赖而导致数据的不一致性,或是核心服务出现异常。

高可用包括 去掉IDC机房内部的 single of failure, 也包括 去掉 IDC机房之间的 single of failure,

去掉IDC机房内部的 single of failure,参见下面的案例

《》

《》

去掉 IDC机房之间的 single of failure,主要是异地多活

《》

《》

《》

关于高可用的系统化介绍,请参见尼恩 《》

黄金法则5: 高性能法则

主要是无锁化编程

比如 netty 就用了很多 无锁化架构

具体,请参见尼恩的 netty 资源,包括《》和 《穿透Netty架构和源码》视频

比如 Disruptor也 就用了很多 无锁化架构

具体,请参见尼恩的 Disruptor 视频,

关于高性能法则的系统化介绍,请参见尼恩 《》

黄金法则6:高并发读 架构法则

对于读取操作量大的场景 ,使用缓存。

适当的场景,要使用三级缓存。

注意,要配套有 缓存的一致性架构。

具体,请参见 尼恩的 《三级缓存架构与实操》

黄金法则7:高并发写架构法则

对于写入量大的场景 , 使用消息队列进行异步处理。

具体请参见尼恩的 《Rocketmq四部曲》

黄金法则8:静态资源缓存架构法则

对于静态资源,

首先,进行动静分离

然后,对于静态资源,考虑Nginx文件缓存和 CDN。

黄金法则9:垂直扩展架构

垂直扩展架构的核心: 通过提升单节点的能力,线性扩充系统性能。

垂直扩展的方式又有两种:

(1)增强单机硬件性能,例如:增加CPU核数如32核,升级更好的网卡如万兆,升级更好的硬盘如SSD,扩充硬盘容量如2T,扩充系统内存如128G;

(2)提升单机架构性能,例如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间;

单节点的潜力,有极限的。所以,解决单节点的 瓶颈,还是水平扩展。

黄金法则10:水平扩展架构

水平扩展架构的核心: 通过增加服务器数量,线性扩充系统性能。

水平扩展对系统架构设计是有要求的,如何在架构各层进行可水平扩展的设计。

DB的水平扩展:在数据量很大的情况下,DB涉及数据的水平扩展,将原本存储在一台服务器上的数据水平拆分到不同服务器上去,以达到扩充系统性能的目的。

redis的水平扩展:在数据量很大的情况下,使用redis Cluster 替代单节点的redis。

服务层的水平扩展: 使用分布式的微服务架构,替代单体应用。

黄金法则11: 索引架构法则

高性能数据查询,需要索引。

目前大多数流行的索引是基于B-Tree或LSM(Log Structured Merge) Tree这两种数据结构来设计的。

  • B-Tree

像Oracle、SQL Server、DB2、MySQL (InnoDB)和PostgreSQL这些传统的关系数据库依赖的底层存储引擎是基于B-Tree开发的;

  • LSM Tree

像Clickhouse、Cassandra、Elasticsearch (Lucene)、Google Bigtable、Apache HBase、LevelDB和RocksDB这些当前比较流行的NoSQL数据库存储引擎是基于LSM开发的。

两种结构,使用与不同场景,当写读比例很大的时候(写比读多),LSM树相比于B树有更好的性能

  • 插件式替换模式:

大部分中间件,想办法兼容两个场景,所以,会采用了插件式的存储引擎架构,Server层和存储层进行解耦。

所以,大部分中间件,同时支持多种存储引擎。

比如,MySQL既可以支持B-Tree结构的InnoDB存储引擎,还可以支持LSM结构的RocksDB存储引擎。

比如,MongoDB采用了插件式存储引擎架构,底层的WiredTiger存储引擎还可以支持B-Tree和LSM两种结构组织数据,但MongoDB在使用WiredTiger作为存储引擎时,目前默认配置是使用了B-Tree结构。

黄金法则12:事务性数据存储架构法则

对于需要事务性的数据操作,也就是需要

  • ?原子性
  • ?一致性
  • ?隔离性
  • D持久性

事务性数据操作架构场景,使用 RDBMS/SQL 数据库。

黄金法则13:非结构化数据存储架构法则

对于非强事务的数据操作,或者非结构化的文档数据,使用NoSQL

注意Nosql的选型,具体请参见尼恩的博客文章

其中,有一个重要的文章,可以参考

黄金法则14: 复杂对象存储架构法则

对于复杂的数据,比如文件、图像、视频、音频等

选择对象存储,比如minio。

黄金法则15:高性能搜索的架构法则

如果是海量数据需要全文搜索,需要使用搜索索引,比如ElasticSearch。

这时候,需要考虑全量数据和ElasticSearch的数据一致性问题。

黄金法则16:海量结构化数据的扩展架构

亿级库表规模架构设计

百亿级库表架构设计

具体,请参见尼恩 《Java高并发核心编程卷3 加强版》

黄金法则17:图形数据存储架构

图形数据(具有节点、边和关系的数据)存储场景,利用图形数据库,比如neo4j。

其实用起来很简单,尼恩在数据中台架构中,用neo4j 存储过数据血缘。

黄金法则18:时序数据存储架构

对于与时间序列有关的数据,比如iot监控数据、系统监控数据(如Prometheus),需要用到时序数据存储

时序数据库全称为时间序列数据库。时间序列数据库指主要用于处理带时间标签(按照时间的顺序变化,即时间序列化)的数据,带时间标签的数据也称为时间序列数据。与传统的关系型数据库不同,时序数据库能够高效地处理大量时间序列数据,适用于各种领域和应用场景,如物联网、金融市场、工业监控等。

类似的一些比较常见的框架:

  • InfluxDB:一个流数据平台,专注于存储、查询和分析大规模、高维度的数据。它支持 SQL 查询和 InfluxQL 查询,可以多维度的对数据进行可视化和分析。

  • TimescaleDB:一个开源的关系型数据库,支持高效、高可扩展的时序数据存储和高级时序数据分析。

  • OpenTSDB:一个分布式的时序数据存储系统,支持海量数据存储,并提供了大量的数据查询API和数据可视化选项。

  • CrateDB:新兴的开源分布式 SQL 数据库,具有高可扩展性和高速度,目前已成为处理实时数据的优选解决方案之一。

黄金法则19:队列缓冲+批处理法则

在高并发场景,可以用队列对数据进行缓冲, 然后通过异步批处理的模式,提升性能。

比如 Netty源码中的队列缓冲+批处理架构

比如 消息队列写入场景的队列缓冲+批处理架构

比如 DB写入场景的队列缓冲+批处理架构

黄金法则20:预加载架构

预加载是一种常见的优化技术,它可以提高程序的性能和响应速度。

预加载,指的是预先加载对象或资源到内存中,以便在程序执行过程中能够更快地访问这些对象或资源。

通过预加载,可以避免在程序运行过程中频繁地加载对象,从而提高程序的性能和响应速度。

预加载的场景

  • 比如hotkey的缓存预加载

  • 比如一些耗时的资源可以预加载,比如数据库连接、文件等,以便在程序执行过程中能够更快地访问这些资源。

单例模式的 饿汉子模式,就属于 预加载架构的内存

具体请参见尼恩的《Java高并发核心编程卷2》

黄金法则21:懒加载架构

延迟加载是指在第一次访问对象时,或在第一次使用资源时再加载,而不是在程序启动时就加载。

延迟加载可以减少程序启动时间,并在真正需要使用对象或资源时才进行加载。

比如经典的CachAside 模式,就属于懒加载架构

CachAside 模式,请参见尼恩的《Java高并发核心编程卷3 加强版》

比如经典的DCL 双检锁,就属于懒加载架构

DCL 双检锁,请参见尼恩的《Java高并发核心编程卷2 加强版》

黄金法则22:单一责任原则(SRP)

SRP是微服务架构重要的原则。

每个微服务都应该负责一个单一的业务,并确保做好这个业务,这个业务粒度的大小取决于你对业务和架构综合考虑。

SRP能够确保微服务职责单一性、功能完整性拆分, 这样,就便于维护、测试和部署。

注意:请点击图像以查看清晰的视图!

黄金法则23:松耦合原则

什么事松耦合:松耦合是指每个微服务都应该是独立的,并通过API与其他服务进行通信。

松耦合的优势:可以降低 级联故障 的风险,也可以提高服务可扩展性,提高微服务的可复用性。

尽量做彻底解耦,包含数据库层的解耦:

  • 数据库层的解耦,就是避免一个微服务与其他微服务共享数据库,因为这可能会导致数据不一致,并且会使故障排查变得非常困难。
  • 每个微服务也都应该只管理自己的数据,每个微服务都有自己的数据库来存储数据,以确保可扩展性和可靠性。

在设计微服务时,应该专注于创建小型、松散耦合和高度内聚的服务。

注意:请点击图像以查看清晰的视图!

黄金法则24:领域驱动原则,不数据驱动原则,也不是界面驱动原则

DDD是一种软件设计方法,它专注于特定业务领域的软件设计。

微服务架构、微服务设计非常适合采用DDD,为啥呢?

因为每个服务都可以设计为特定业务领域的具体实现。

注意:请点击图像以查看清晰的视图!

领域驱动设计,首先应建立领域模型,确定领域限界上下文,然后才进行微服务拆分,

如果是 数据驱动原则/界面驱动原则 ,那么,是一上来就定义数据库表结构,就去调整领域逻辑代码。

领域模型和领域服务应具有高度通用性、稳定性,通过接口层和应用层屏蔽外部变化对业务逻辑的影响,保证核心业务功能的稳定性。

基于领域模型进行拆分,围绕业务领域按职责单一性、功能完整性拆分。

黄金法则25:架构分层职责明确,严守调用规范,规避 “微服务小泥球”

老的单体架构, 常常被成为大泥球。

“大泥球”单体,主要的问题

  • 代码腐化:业务代码经过长时间的迭代,有很多重复代码。比如一个功能可能有 3,4 种实现。
  • 业务逻辑交织:业务应用经过长时间发展,功能变多,业务功能里的逻辑代码可能相互引用,交织不清。
  • 代码复杂:功能多,业务逻辑复杂,只有少数员工能理解。这也是代码腐化一种。
  • 维护性变差:修改 bug 或增加新功能时,牵一发而动全身。一个 bug 没修好可能导致整个软件不可用。
  • 扩展性变差:增加新功能时,牵一发而动全身。
  • 编译发布变长:软件代码量大,编译时长变长,导致发布时长也变长。

化解“大泥球”单体的措施,是微服务架构。微服务架构最基本的一个点:分而治之,由大化小。

  • 松耦合:划分为一个一个小的微服务,代码之间逻辑交织降低。
  • 独立部署:每个划分的微服务都是一个独立的项目,可以独立部署。
  • 编译发布改善:划分为独立的小项目,编译时长变短,发布时长相应变短。
  • 故障隔离:由于划分为一个一个微服务,故障仅发生在独立的微服内。
  • 可扩展性:每个服务可以独立横向扩展,也可以从应用程序中提出独立功能变成服务,扩展变强。
  • 职责单一团队:每个小的微服务都由一个小型的高度专注的团队负责。
  • 技术异构:每个团队可以选择适合该业务的技术。

微服务架构目的就是把一个大单体划分为各种微服务,松耦合,独立自治。

微服务架构把一个大泥球,变成了很多个小而美的颗粒。

每个小颗粒职责单一,边界明确,可以通过简单组装完成大的功能,自然就比之前的大泥球好处理得多

但是,迭代过程中,出现了一种奇怪现象,微服务内部没有进行内部的模块划分,代码耦合严重,调用关系混乱,就像一个小泥球。

在腾讯视频的DDD重构案例中,在老的微服务架构中,存在分层不明确,下层服务过于理解业务逻辑,存在下层调用上层的问题,出现了代码耦合严重,调用关系混乱的 “微服务小泥球”。

具体请参考《》

在腾讯视频的DDD重构的过程中,明确架构分层,降低模块间不必要的耦合;

严格遵守分层架构原则,上层服务可调用下层服务,下层服务不涉及业务逻辑。如上下层服务需交互,可通过逻辑解耦方式实现,如消息队列或中转。

如果规避 “微服务小泥球”?各层职能定位清晰,只能上层调用下层,也就是说只能从外层调用内层服务,下层服务通过封装、组合或编排对上层暴露,服务粒度由细到粗。

微服中,各层职能定位清晰:

  • 基础层为各层提供资源服务
  • 领域层负责领域业务逻辑的实现
  • 应用层负责服务的编排和组合
  • 接口层对外进行服务暴露

注意:请点击图像以查看清晰的视图!

黄金法则26:进行全方位的监控、记录

监控和日志记录对于微服务架构的安全、维护和调优都至关重要。

在拥有数百个微服务的项目中开发的主要困难之一是调试非常困难,因为服务分散、日志分散,很难找到失败的原因。

因此,每个服务都应该有日志记录和监控措施,以跟踪其性能并检测错误。

注意:请点击图像以查看清晰的视图!

黄金法则27:开发运维一体化法则

CI/CD是一种软件开发运维过程实践,打通开发和运维环节,实现应用程序的构建、测试和部署自动化。

任何微服务都应该是可持续部署的,实现微服务的快速高效部署,缩短了微服务上线时间。

注意:请点击图像以查看清晰的视图!

总之,采用微服务架构开发有许多优势,但要确保为微服务系统成功实施就需要遵循一些设计原则。

包括但不限于上面介绍的几个基础原则,在此基础上还需要有与所在领域或者行业的做定制化优化实践。

黄金法则28: API 网关法则

API 网关是伴随着微服务架构一同引入的基础设施。

一般来说,随着服务化在公司内的迅速推进,网关逐步成为应用程序暴露在外网的标准解决方案。

前面,已经梳理了下面的经典案例:

  • 《》
  • 《》
  • 《》
  • 《》
  • 《》
  • 《》
  • 《》
  • 《》
  • 《》
  • 《》

黄金法则29: 冗余法则

单点故障是指在一个系统中出现的只有一个组件或节点导致整个系统停止工作或无法正常运行的情况。

当系统中的某个关键组件或节点发生故障时,可能会引发连锁反应,导致整个系统崩溃或无法提供正常的服务。

单点故障是系统中的薄弱环节,其发生故障的概率相对较高。

在计算机网络、电力系统、交通运输系统等各个领域都存在单点故障的风险。一旦发生单点故障,可能会导致系统停止运行,造成重大的经济损失和社会影响。

单点故障可以发生在硬件层面,如计算机服务器、网络交换机等设备发生故障;

单点故障也可以发生在软件层面,如程序运行错误、数据库崩溃等。此外,还有可能是人为因素导致的单点故障,如误操作、管理失误等。

为了避免单点故障对系统造成的影响,核心是 冗余法则。

冗余法则,也就是冗余设计,即在系统中引入冗余组件或节点,当一个组件或节点发生故障时,可以自动切换到备用组件或节点,保证系统的连续可用性。

总之,单点故障是系统中非常重要但相对薄弱的环节,一旦发生故障可能会对整个系统造成严重影响。

因此,必须重视并采取相应的措施来预防和应对单点故障的发生,确保系统的稳定运行和连续可用性。

黄金法则30: 数据容错法则

数据容错:让错误不再蔓延

数据容错是指通过技术手段,避免因硬件故障、软件错误、人为操作失误等原因导致的数据错误。、

常见的数据容错方法包括冗余技术、校验和检查、自动恢复技术等。

(1)冗余技术:通过在系统中添加额外的硬件或软件组件,提高系统的可靠性。例如,使用双电源、双硬盘等,确保在某个部件发生故障时,系统仍能正常运行。

(2)校验和检查:通过计算数据的校验和,在数据传输或存储过程中进行检查。如果数据发生错误,可以通过校验和及时发现并纠正。

(3)自动恢复技术:通过备份和恢复系统中的数据,确保在发生故障时能迅速恢复数据。例如,使用RAID技术、定期备份数据等。

黄金法则31:数据容灾法则

数据容灾:未雨绸缪,灾难无虞

数据容灾是指在灾难发生时,通过技术手段和备份策略,确保数据不会丢失或损坏。

常见的数据容灾方法包括远程备份、数据快照、镜像复制等。

(1)远程备份:在远离灾难发生地的位置备份数据,确保在灾难发生时数据不会丢失。同时,要定期测试备份数据的可访问性和完整性。

(2)数据快照:通过定时拍摄数据快照,记录数据的最新状态。在灾难发生时,可以通过回滚到快照时间点的状态,迅速恢复数据。

(3)镜像复制:将数据复制到远程站点,确保在灾难发生时可以通过远程站点快速恢复数据。同时,要确保复制数据的同步性和完整性。

黄金法则30: 心跳法则

分布式心跳机制是着重使用于分布式系统中,主要是为了确保系统中的各个节点状态保持高可用性,保证系统的正常运行。

心跳机制的主要功能就是短时间内确认对方的存活状态,使用心跳机制就可以简单实现各个节点的状态信息的可靠传输,避免无用的信息流传递,从而提高系统的效率。

心跳机制主要包括两部分:发送端发送心跳信号、接收端接收心跳信号,当接收端收到发送端发送的心跳信号时,进行确认,从而保证信号的传输的可靠性;发送端没有收到接收端的确认,则可以重复发送心跳信号,提高系统的可用性。

黄金法则32:限流法则

限流在很多场景中用来限制并发和请求量,比如说秒杀抢购,保护自身系统和下游系统不被巨型流量冲垮等。

以微博为例,例如某某明星公布了恋情,访问从平时的50万增加到了500万,系统的规划能力,最多可以支撑200万访问,那么就要执行限流规则,保证是一个可用的状态,不至于服务器崩溃,所有请求不可用。

黄金法则33:熔断法则

具体参见 《尼恩Java高并发核心卷3》

黄金法则34:隔离架构

隔离架构的一个典型案例,如舱壁模式

具体参见 《尼恩Java高并发核心卷3》

黄金法则34:一致性hash

分治模式在存储领域的使用:数据分⽚

数据分⽚指按照某个维度将存放在单⼀数据库中的数据, 分散地存放⾄多个数据库或表中以达到提升性能瓶颈以及可⽤性的效果。

主要的分片算法
  • range 分片
  • ID取模分片
  • hash 哈希分布
  • 一致性hash
range 分片

一种是按照 range 来分,就是每个片,一段连续的数据,这个一般是按比如时间范围/数据范围来的,但是这种一般较少用,因为很容易发生数据倾斜,大量的流量都打在最新的数据上了。

比如,安装数据范围分片,把1到100个数字,要保存在3个节点上

按照顺序分片,把数据平均分配三个节点上

  • 1号到33号数据保存到节点1上
  • 34号到66号数据保存到节点2上
  • 67号到100号数据保存到节点3上

ID取模分片

此种分片规则将数据分成n份(通常dn节点也为n),从而将数据均匀的分布于各个表中,或者各节点上。

扩容方便。

ID取模分片常用在关系型数据库的设计

具体请参见 秒杀视频的 亿级库表架构设计

hash 哈希分布

使用hash 算法,获取key的哈希结果,再按照规则进行分片,这样可以保证数据被打散,同时保证数据分布的比较均匀

哈希分布方式分为三个分片方式:

  • 哈希取余分片
  • 一致性哈希分片
  • 虚拟槽分片
哈希取余模分片

例如1到100个数字,对每个数字进行哈希运算,然后对每个数的哈希结果除以节点数进行取余,余数为1则保存在第1个节点上,余数为2则保存在第2个节点上,余数为0则保存在第3个节点,这样可以保证数据被打散,同时保证数据分布的比较均匀

比如有100个数据,对每个数据进行hash运算之后,与节点数进行取余运算,根据余数不同保存在不同的节点上

哈希取余分片是非常简单的一种分片方式

哈希取余分片优点:

  • 配置简单:对数据进行哈希,然后取余

哈希取余分片缺点:

  • 数据节点伸缩时,导致数据迁移
  • 迁移数量和添加节点数据有关,建议翻倍扩容
一致性哈希分片

一致性哈希原理:

将所有的数据当做一个token环,

token环中的数据范围是0到2的32次方。

然后为每一个数据节点分配一个token范围值,这个节点就负责保存这个范围内的数据。

对每一个key进行hash运算,被哈希后的结果在哪个token的范围内,则按顺时针去找最近的节点,这个key将会被保存在这个节点上。

一致性哈希分片的节点扩容

在下面的图中:

  • 有4个key被hash之后的值在在n1节点和n2节点之间,按照顺时针规则,这4个key都会被保存在n2节点上
  • 如果在n1节点和n2节点之间添加n5节点,当下次有key被hash之后的值在n1节点和n5节点之间,这些key就会被保存在n5节点上面了

下图的例子里,添加n5节点之后:

  • 数据迁移会在n1节点和n2节点之间进行
  • n3节点和n4节点不受影响
  • 数据迁移范围被缩小很多

同理,如果有1000个节点,此时添加一个节点,受影响的节点范围最多只有千分之2。所以,一致性哈希一般用在节点比较多的时候,节点越多,扩容时受影响的节点范围越少

分片方式:哈希 + 顺时针(优化取余)

一致性哈希分片优点:

  • 一致性哈希算法解决了分布式下数据分布问题。比如在缓存系统中,通过一致性哈希算法把缓存键映射到不同的节点上,由于算法中虚拟节点的存在,哈希结果一般情况下比较均匀。
  • 节点伸缩时,只影响邻近节点,但是还是有数据迁移

“但没有一种解决方案是银弹,能适用于任何场景。所以实践中一致性哈希算法有哪些缺陷,或者有哪些场景不适用呢?”

一致性哈希分片缺点:

一致性哈希在大批量的数据场景下负载更加均衡,但是在数据规模小的场景下,会出现单位时间内某个节点完全空闲的情况出现。

黄金法则35:Gossip 协议 法则

gossip协议,顾名思义,就像流言蜚语一样,利用一种随机、带有传染性的方式,将信息传播到整个网络中,并在一定时间内,使得系统内的所有节点数据一致。

去中心化的通讯场景,可以使用Gossip 协议。

Gossip是一种去中心化思路的分布式协议,解决信息在集群中的传播和最终一致性。

黄金法则36:WebSocket推送 法则

服务端向客户端的推送,使用WebSocket

最好使用Netty假设WEBSocket 服务器,单节点支持100W连接

黄金法则37:内存池 法则

内存池(Memory Pool)是一种内存分配方式。

内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升。

具体 参见Netty 内存池、 Golang 中的内存池

黄金法则38:对象池 法则

如果一个类被频繁请求使用,那么不必每次都生成一个实例,可以将这个类都一些实例保存到一个“池”中,待需要使用的时候直接从“池”中获取。

这个“池”就被称为对象池,它可以是一个数组,一个链表或者任何集合。

对象池其实就是一个集合,里面包含了我们需要的对象集合,当然这些对象都被池化了,也就是被对象池所管理,想要这样的对象,从池子里取个就行,但是用完得归还。

对象池的对象最好是创建比较费时的大对象。

如果是太简单的对象,再进入池化的时间比自己构建还多,就不划算了。但是对于有些对象来说,其创建的代价还是比较昂贵的,比如线程、tcp连接、rpc连接、数据库连接等对象,因此对象池技术还是有其存在的意义。

在程序中使用数据库连接池和线程池,可以理解为一种特殊的对象池, 可以有效的改善系统在高并发下的性能,这是两个非常重要的性能组件,任何对性能敏感的系统,都需要考虑合理配置这两个组件。

Apache 的commons-pool是一个通用的开源"对象池"组件,即通过一定的规则来维护对象集合的容器; 大家常用的dbcp数据库连接池,也是基于commons-pool实现.

commons-pool实现思想非常简单,它主要的作用就是将对象集合池化,任何通过pool进行对象存取的操作,都会严格按照pool配置(比如池的大小)实时的创建对象/阻塞控制/销毁对象等.

commons-pool 实现了对象集合的管理以及对象的分发.

  1. 将创建对象的方式,使用工厂模式;
  2. 通过"pool配置"来约束对象存取的时机
  3. 将对象列表保存在队列中(LinkedList)

另外,Netty 也提供了自己的 对象池实现, 尼恩在第35章视频中,会给大家做系统化,体系化的介绍。

黄金法则39:CAP法则

分布式系统中有一个重要理论:CAP。

  1. C:一致性(Consistency)

    在分布式系统中,数据会在多个副本中存在,一些问题可能导致在写入数据时,部分副本成功,部分副本失败,从而导致数据不一致。一致性 C 的要求是,数据更新操作成功后,多个副本的数据必须保持一致。

  2. A:可用性(Availability)

    无论何时,客户端对集群进行读写操作,请求都应能得到正常的响应。

  3. P:分区容错性(Partition Tolerance)

    当发生通信故障,集群被分割成多个无法通信的分区时,集群仍应能正常运行。

CAP的一个重要结论:AP、CP 是不能同时满足的,这是铁律。

黄金法则40:最终一致性

AP、CP 是不能同时满足的,这是铁律。

AP、CP的权衡——最终一致性。

往往为了AP,忍痛放弃强一致支持,转而追求最终一致性。

大部分业务场景下,我们是可以接受短暂的不一致的。

说在最后:有问题找老架构取经

以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

在面试之前,建议大家系统化的刷一波 5000页《》,里边有大量的大厂真题、面试难题、架构难题。很多小伙伴刷完后, 吊打面试官, 大厂横着走。

在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。

遇到职业难题,找老架构取经, 可以省去太多的折腾,省去太多的弯路。

尼恩指导了大量的小伙伴上岸,前段时间,刚指导一个40岁+被裁小伙伴,拿到了一个年薪100W的offer。

狠狠卷,实现 “offer自由” 很容易的, 前段时间一个武汉的跟着尼恩卷了2年的小伙伴, 在极度严寒/痛苦被裁的环境下, offer拿到手软, 实现真正的 “offer自由” 。

尼恩技术圣经系列PDF

  • 《》
  • 《》
  • 《》
  • 《》
  • 《》
  • 《》
  • 《》
  • 《》

……完整版尼恩技术圣经PDF集群,请找尼恩领取

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓

显示全文