Spiga

分类为架构设计的文章

分布式架构之性能设计

2025-09-06 23:03:29

摘要:一、缓存 基本上来说,在分布式系统中最耗性能的地方就是最后端的数据库了。 一般来说,只要小心维护好,数据库四种操作(select、update、insert 和 delete)中的三个写操作 insert、update 和 delete 不太会出现性能问题(insert 一般不会有性能问题,update 和 delete 一般会有主键,所以也不会太慢)。除非索引建得太多,而数据库里的数据又太多,这三个操作才会变慢。 绝大多数情况下,select 是出现性能问题最大的地方。一方面,select 会有很多像 join、group、order、like 等这样丰富的语义,而这些语义是非常耗性能的;另一方面,大多数应用都是读多写少,所以加剧了慢查询的问题。 分布式系统中远程调用也会消耗很多资源,因为网络开销会导致整体的响应时间下降。为了挽救这样的性能开销,在业务允许的情况下,使用缓存是非常必要的事情。 缓存是提高性能最好的方式,一般来说,缓存有以下三种模式。 1. Cache Aside 更新模式 这是最常用的设计模式了,其具体逻辑如下。 失效:应用程序先从 Cache 取数据,如果没有得到,则从数据库中取数据,成功后,放到缓存中。 命中:应用程序从 Cache 中取数据,取到后返回。 更新:先把数据存到数据库中,成功后,再让缓存失效。 这是标准的设计模式,为什么不是写完数据库后更新缓存?主要是怕两个并发的写操作导致脏数据。 那么,是不是这个 Cache Aside 就不会有并发问题了?不是的。比如,一个是读操作,但是没有命中缓存,就会到数据库中取数据。而此时来了一个写操作,写完数据库后,让缓存失效,然后之前的那个读操作再把老的数据放进去,所以会造成脏数据。 这个案例理论上会出现,但实际上出现的概率可能非常低,因为这个条件需要发生在读缓存时缓存失效,而且有一个并发的写操作。实际上数据库的写操作会比读操作慢得多,而且还要锁表,读操作必须在写操作前进入数据库操作,又要晚于写操作更新缓存,所有这些条件都具备的概率并不大。 当然,最好还是为缓存设置好过期时间。 2. Read/Write Through 更新模式 在 Cache Aside 套路中,应用代码需要维护两个数据存储,一个是缓存,一个是数据库。所以,应用程序比较啰嗦。而 Read/Write Through 套路…… 阅读全文

分布式架构之管理设计

2025-08-30 20:38:31

摘要:一、分布式锁 我们知道,在多线程情况下访问一些共享资源需要加锁,不然就会出现数据被写乱的问题。在分布式系统下,这样的问题也是一样的。只不过,我们需要一个分布式的锁服务。 分布式的锁服务需要有以下几个特点。 安全性(Safety):在任意时刻,只有一个客户端可以获得锁(排他性)。 避免死锁:客户端最终一定可以获得锁,即使锁住某个资源的客户端在释放锁之前崩溃或者网络不可达。 容错性:只要锁服务集群中的大部分节点存活,Client 就可以进行加锁解锁操作。 1. Redis 的分布式锁服务 我们通过以下命令对资源加锁。 SET resource_name my_random_value NX PX 30000 解释一下: SET NX 命令只会在 key 不存在的时候给 key 赋值,PX 命令通知 Redis 保存这个 key 30000ms。 my_random_value 必须是全局唯一的值。这个随机数在释放锁时保证释放锁操作的安全性。 PX 操作后面的参数代表的是这个 key 的存活时间,称作锁过期时间。 当资源被锁定超过这个时间时,锁将自动释放。 获得锁的客户端如果没有在这个时间窗口内完成操作,就可能会有其他客户端获得锁,引起争用问题。 通过下面的脚本为申请成功的锁解锁: if redis.call(get,KEYS[1]) == ARGV[1] then return redis.call(del,KEYS[1]) else return 0 end 如果 key 对应的 value 一致,则删除这个 key。通过这个方式释放锁是为了避免 Client 释放了其他 Client 申请的锁。 2. 分布式锁服务的一个问题 虽然 Redis 文档里说他们的分布式锁是没有问题的,但其实还是很有问题的。尤其是上面那个为了避免 Client 端把锁占住不释放,然后,Redis 在超时后把其释放掉,这事儿听起来就有点不靠谱。 我们来脑补一下,不难发现下面这个案例。 1. 如果 Client A 先取得了锁。 2. Client B 在等待 Client A 的工作完成。 3. 这个时候,如果 Client A 被挂在了某些事上,比如一个外部的阻塞调用,或是 CPU 被别的进程吃满,或是不巧碰上了 Full GC,导致 Client …… 阅读全文

分布式架构之弹力设计

2025-08-24 23:12:10

摘要:对于分布式系统的容错设计,在英文中又叫 Resiliency(弹力)。意思是,系统在不健康、不顺,甚至出错的情况下有能力 hold 得住,挺得住,还有能在这种逆境下力挽狂澜的能力。其中着眼于分布式系统的各种“容忍”能力,包括服务隔离、异步调用、请求幂等性、可伸缩性(有 / 无状态的服务)、一致性(补偿事务、重试)、应对大流量的能力(熔断、降级)。可以看到,在确保系统正确性的前提下,系统的可用性是弹力设计保障的重点。 我们很难计算我们设计的系统有多少的可用性,因为影响一个系统的因素实在是太多了,除了软件设计,还有硬件,还有第三方服务(如电信联通的宽带 SLA),当然包括“建筑施工队的挖掘机”,宕机原因主要有以下这些: 网络问题。网络链接出现问题,网络带宽出现拥塞…… 性能问题。数据库慢 SQL、Java Full GC、硬盘 IO 过大、CPU 飙高、内存不足…… 安全问题。被网络攻击,如 DDoS 等。 运维问题。系统总是在被更新和修改,架构也在不断地被调整,监控问题…… 管理问题。没有梳理出关键服务以及服务的依赖关系,运行信息没有和控制系统同步…… 硬件问题。硬盘损坏、网卡出问题、交换机出问题、机房掉电、挖掘机问题…… 一个分布式系统的故障是非常复杂的,因为故障是分布式的、多米诺骨牌式的。所以,要充分地意识到下面两个事。 故障是正常的,而且是常见的。 故障是不可预测突发的,而且相当难缠。 这就是为什么我们把这个设计叫做弹力(Resiliency)。 一方面,在好的情况下,这个事对于我们的用户和内部运维来说是完全透明的,系统自动修复不需要人的干预。 另一方面,如果修复不了,系统能够做自我保护,而不让事态变糟糕。 一、隔离设计 隔离设计对应的单词是 Bulkheads,中文翻译为隔板,这个概念来自于船舱里防漏水的隔板。我们的软件设计当然也“漏水”,所以为了不让“故障”蔓延开来,需要使用“隔板”技术,来将架构分隔成多个“船舱”来隔离故障。 1. 按服务的种类来做分离 上图中,我们将系统分成了用户、商品、社区三个板块。这三个块分别使用不同的域名、服务器和数据库,做到从接入层到应用层再到数据层三层完全隔离。这样一来,在物理上来说,一个板块的故障就不会影响到另一板块。 上面这种架构虽然在系统隔离上做得比较好,但是也存在以下一些问题。 如果我们需要同时获得多…… 阅读全文

分布式架构之本质

2025-08-23 21:03:23

摘要:我们一直在谈论各式各样的架构,如高并发架构、异地多活架构、容器化架构、微服务架构、高可用架构、弹性化架构等。还有和这些架构相关的管理型的技术方法,如 DevOps、应用监控、自动化运维、SOA 服务治理、去 IOE 等。面对这么多纷乱的技术,很多团队或是公司都是一个一个地去做这些技术,非常辛苦,也非常累。 接下来我们来谈一谈分布式架构。 一、概述 1. 分布式的优缺点 首先,为什么需要分布式系统,而不是传统的单体架构。 增大系统容量。我们的业务量越来越大,而要能应对越来越大的业务量,一台机器的性能已经无法满足了,我们需要多台机器才能应对大规模的应用场景。所以,我们需要垂直或是水平拆分业务系统,让其变成一个分布式的架构。 加强系统可用。我们的业务越来越关键,需要提高整个系统架构的可用性,这就意味着架构中不能存在单点故障。这样,整个系统不会因为一台机器出故障而导致整体不可用。所以,需要通过分布式架构来冗余系统以消除单点故障,从而提高系统的可用性。 当然,分布式系统还有一些优势,比如: 因为模块化,所以系统模块重用度更高; 因为软件服务模块被拆分,开发和发布速度可以并行而变得更快; 系统扩展性更高;团队协作流程也会得到改善; …… 不过,这个世界上不存在完美的技术方案,采用任何技术方案都是“按下葫芦浮起瓢”,都是有得有失,都是一种 trade-off。也就是说,分布式系统在解决上述问题的同时,也给我们带来了其他的问题。因此,我们需要清楚地知道分布式系统所带来的问题。 从上面的表格我们可以看到,分布式系统虽然有一些优势,但也存在一些问题。 架构设计变得复杂(尤其是其中的分布式事务)。 部署单个服务会比较快,但是如果一次部署需要多个服务,流程会变得复杂。 系统的吞吐量会变大,但是响应时间会变长。 运维复杂度会因为服务变多而变得很复杂。 架构复杂导致学习曲线变大。 测试和查错的复杂度增大。 技术多元化,这会带来维护和运维的复杂度。 管理分布式系统中的服务和调度变得困难和复杂。 2. 面向服务的架构有以下三个阶段 下面是一个 SOA 架构的演化图。 我们可以看到,面向服务的架构有以下三个阶段。 20 世纪 90 年代前,是单体架构,软件模块高度耦合。当然,这张图同样也说明了有的 SOA 架构其实和单体架构没什么两样,因为都是高度耦合在一起的。就像图中的齿轮一…… 阅读全文

Go学习笔记(九):实现Micro-Kernel(微内核模式)

2020-05-01 20:44:02

摘要:什么是微内核架构 微内核架构(Microkernel Architecture),也被称为插件化架构(Plugin-in Architecture),是一种面向功能进行拆分的可扩展架构。例如 VS Code、Eclipse 这一类 IDE 软件、UNIX 操作系统等等,都是参照微内核架构设计实现的。 微内核架构的两个核心组件 微内核架构包含两类核心的组件:核心系统(Core System)和插件模块(Plug-in modules)。核心系统负责与具体功能无关的通用功能,例如应用生命周期的管理、插件模块的管理(包括:插件模块的注册、载入、卸载等等);插件模块负责实现具体的功能,例如一个 Web 框架基本上会按照功能模块拆分成如下的插件模块:路由模块、安全模块、HTTP 编解码模块等等,每个模块都通过插件实现,每一个插件都只做一件事情。 微内核基本架构示意图如下所示: 核心系统功能尽量保持稳定,不要因为插件模块的扩展而不断修改,插件模块可以根据功能需求进行不断扩展。 特点与要点 特点 易于扩展 错误隔离 保持架构⼀致性 要点 内核包含公共流程或通⽤逻辑 将可变或可扩展部分规划为扩展点 抽象扩展点⾏为,定义接⼝ 利⽤插件进⾏扩展 实例 如下图,我们希望实现Agent在系统主机上,这个Agent可以手机文件信息、进程信息、应用信息,以及提供一个扩展点,可以扩展未来其他要收集的信息,因此我们需要提供一个Extension Point。 1.接口Collector定义 type Collector interface { Init(evtReceiver EventReceiver) error Start(agtCtx context.Context) error Stop() error Destory() error } type Event struct { Source string Content string } type EventReceiver interface { OnEvent(evt Event) } 2.定义Agent结构体 type Agent struct { collectors map[string]Collector evtBuf chan Event cancel c…… 阅读全文

Go学习笔记(八):实现Pipe-Filter(管道过滤器)

2020-04-27 22:50:03

摘要:Pipe-Filter 模式,即管道过滤器模式,这是一种非常经典的架构模式,这种模式与工业制造生产流水线非常类似,就像薯片的生产过程,从土豆的清洗、去皮、切片、烘干、油炸,到最后打包完成,整个生产过程被拆分成了多个环节,每个环节处理完成之后,通过传送带传送到下一个环节的机器。整个生产过程每个环节都是独立的,但又环环相扣,只要有一个环节出问题了,生产出来的薯片就会有质量问题。 适用的场景 ⾮常适合与数据处理及数据分析系统 Filter封装数据处理的功能 Pipe⽤于连接Filter传递数据或者在异步处理过程中缓冲数据流 进程内同步调⽤时,pipe演变为数据在⽅法调⽤间传递 松耦合:Filter只跟数据(格式)耦合 Filter 和组合模式 23 个经典设计模式里面有一个设计模式叫组合模式,当 Pipe-Filter 遇上组合模式时,多个 Filter 又可以再组合成一个新的 Filter,如下图所示,组合出来的 Filter 接收的数据与第一个 Filter 保持一致,返回的数据与最后一个 Filter 保持一致。通过组合,就可以将多个简单的 Filter 可以组合成一个更复杂的 Filter。应用这一套理论去实践,我们会发现,Filter 既可以做的很轻便,也可以做得很强大。 实例 接下来我们用Go语言实现上图实例: 1.定义filter接口 // Package pipefilter is to define the interfaces and the structures for pipe-filter style implementation package pipefilter // Request is the input of the filter type Request interface{} // Response is the output of the filter type Response interface{} // Filter interface is the definition of the data processing components // Pipe-Filter structure type Filter interface { Process(data Request) (Respons…… 阅读全文

微软云平台Microsoft Azure

2019-09-13 17:27:26

摘要:持续集成、继续部署、继续交付 持续集成(Continuous integration) 是一种软件开发实践,即团队开发成员经常集成它们的工作, 通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。 每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。 持续部署(continuous deployment) 是通过自动化的构建、测试和部署循环来快速交付高质量的产品。 某种程度上代表了一个开发团队工程化的程度,毕竟快速运转的互联网公司人力成本会高于机器, 投资机器优化开发流程化相对也提高了人的效率,让 engineering productivity 最大化。 持续交付(英语:Continuous delivery,缩写为 CD) 是一种软件工程手法, 让软件产品的产出过程在一个短周期内完成,以保证软件可以稳定、 持续的保持在随时可以释出的状况。它的目标在于让软件的建置、 测试与释出变得更快以及更频繁。这种方式可以减少软件开发的成本与时间,减少风险。 DevOps DevOps(Development和Operations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。 它是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。 它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运维工作必须紧密合作。 Jenkins Jenkins是实现DevOps的工具 Jenkins是一款开源 CICD 软件,用于自动化各种任务,包括构建、测试和部署软件。 Jenkins 支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序。 特点: 易于安装,只要把jenkins.war部署到servlet容器 易于配置-所有配置都通过其提供的web界面实现。 集成RSS/E-mail通过RSS发布构建结果或当构件完成是通过e-mail通知。 生成JUnit/TestNG测试报告。 分布式构建支持Jenkins能够让多台计算机一起构建/测试。 文件识别:Jenkins能够跟…… 阅读全文

微服务架构(九):k8s

2018-04-20 16:07:57

摘要:k8s介绍 什么是k8s k8s是一个舵手,专门用来进行给docker掌管方向的,换句话说,就是用来控制docker运行容器的 和docker 是一样的功能。所以就有一个概念cluster 为什么要使用k8s 因为当docker容器异常的时候,docker无法将容器进行重启,如果容器数量比较大 swarm 优点 架构简单,部署运维成本低 docker swarm 集群模式由于原生态集成到docker-engine中,所以首先学习成本低,对于使用docker-engine 1.12版本及以上可以平滑过渡,service服务可以满足动态增减容器个数,同时具备自身的负载均衡,swarm管理者多台设定保证了机器在出错后有一个良好的容灾机制 启动速度快 swarm集群只会有两层交互,容器启动是毫秒级 swarm缺点 1 无法提供更精细的管理 swarm API兼容docker API,所以使得swarm无法提供集群的更加精细的管理 2 网络问题 在网络方面,默认docker容器是通过桥接与NAT和主机外网络通信,这样就出现2个问题,一个是因为是NAT,外部主机无法主动访问到容器内(除了端口映射),另外默认桥接IP是一样的,这样会出现不同主机的容器有相同的IP的情况。这样两容器更加不能通信。同时网络性能方面,有人测试经过桥接的网络性能只有主机网络性能的70%。当然以上问题可以通过其他工具解决,比如用 Flannel 或者 OVS网桥 3 容器可靠性 在容器可靠性方面,相较于Kubernetes的Replication Controllers可以监控并维持容器的生命,swarm在启动时刻可以控制容器启动,在启动后,如果容器或者容器主机崩溃,swarm没有机制来保证容器的运行。 kubernetes优点: 1 管理更趋于完善稳定 kubernetes 集群管理更趋于完善稳定,同时pod功能上比swarm的service更加强大 2 健康机制完善 Replication Controllers可以监控并维持容器的生命 3 轻松应对复杂的网络环境 kubernetes默认使用Flannel作为overlay网络。 Flannel是CoreOS 团队针对 Kubernetes 设计的一个覆盖网络(OverlayNetwork)工具,其目的在于帮助每一个使用 Kuberente…… 阅读全文

微服务设计(八):docker

2018-04-15 10:53:53

摘要: Docker版本 17.03版本之后 1、CE(Community Edition: 社区版) ---- 免费 2、EE(Enterprise Edition: 企业版)---- 收费 windows 安装 条件 1、windows 10 2、开启Hyper-V 3、安装Toolbox 最新版 Toolbox 下载地址: https://www.docker.com/get-docker 点击 Download Desktop and Take a Tutorial,并下载 Windows 的版本 linux安装 1. centos7.0 以上的版本 2. 安装docker 版本仓库 docker版本 2.1 设置仓库       sudo yum install -y yum-utils device-mapper-persistent-data lvm2 2.2 稳定仓库     sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 3. 安装docker(默认安装最新版本) sudo yum install docker-ce docker-ce-cli containerd.io 如果要安装其他版本       要安装特定版本的 Docker Engine-Community,请在存储库中列出可用版本,然后选择并安装:       1、列出并排序您存储库中可用的版本。此示例按版本号(从高到低)对结果进行排序。         yum list docker-ce --showduplicates | sort -r               docker-ce.x86_64 3:18.09.1-3.el7                     docker-ce-stable               docker-ce.x86_64 3:18.09.0-3.el7                     docker-ce-stable               docker-ce.x86_64 18.06.1.ce-3.…… 阅读全文

微服务架构(七):链路监控

2018-04-09 11:32:52

摘要:什么是链路监控 APM 什么是链路 在分布式系统中,完成一个功能 ,需要涉及到许多服务协作,连接这些服务的请求组合起来就是链路, 例如:就好比一台自行车,我想让自行车跑起来,必须使用链条,那么这个链条就是链路。 什么是链路监控 就是用来记录服务之间的请求过程,就是链路监控 为什么要使用链路监控 见图,微服务不使用链路监控 微服务系统正常运行,时间正常情况下,不需要使用监控中心 在微服务调用过程中比较耗时情况 2.1 如何知道是什么地方导致耗时,无法排查是哪一个节点出现了问题 在微服务调用过程中,涉及到哪些微服务情况 3.1 无法知道微服务的调用过程。 在这两个问题的情况下,所以我们需要使用知道微服务之间的调用过程和每一个微服务掉调用过程所需要的时间。 根据场景中出现的问题,来引出链路监控 那么如何解决这两种问题呢,所以出现了链路监控 链路监控框架 Cat :大众点评开发,基于java的实时应用监控平台,包括实时应用监控,业务是监控 Zipkin :java 开发Zipkin是Twitter开源的调用链分析工具,目前基于springcloud sleuth得到了广泛的使用,特点是轻量,使用部署简单 :代码嵌入性强,基于中间件实现, Pinpoint:java开发 Pinpoint是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能强大,接入端无代码侵入 SkyWalking:java 开发 SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。全链路追踪,配置极其简单。没有任何代码入侵。 Naver的Pinpoint、Apache的HTrace、阿里的鹰眼Tracing、京东的Hydra、新浪的Watchman,美团点评的CAT,skywalking等。 根据优点和缺点(也是框架内部的一些配置和对比)进行比较得出结论 两方面考虑 结合框架特点,结合业务场景特点 所以我们选择SkyWalking 微服务系统中如何使用SkyWalking SkyWalking概念 Skywalking Agent: SkyWalking客户端,用来发送链路数据到Collecter SkyWalking Collecter:…… 阅读全文