Spiga

分类为架构设计的文章

B站架构设计4:历史记录架构设计

2021-08-28 13:54:56

摘要:一、功能设计 为了大部分用户的基本功能体验,满足用户需求,例如播放历史查看、播放进度同步等。离线型用户,app 本地保留历史记录数据。 同样的,也要考虑平台化,视频、文章、漫画等业务扩展接入。 变更功能:添加记录、删除记录、清空历史。 读取功能:按照 timeline 返回 top N,点查获取进度信息。 其他功能:暂停/恢复记录,首次观察增加经验等。 历史记录类型的业务,是一个极高 tps 写入,高 qps 读取的业务服务。分析清楚系统的 hot path,投入优化,而不是哪哪都去优化。 二、架构设计 1. 概述 BFF(app-interface、history):历史 BFF 层接受来自外部用户的读请求,依赖其他例如稿件、漫画服务来组装完整的面向历史业务(页面)需要的数据的组合。同时接受来自内部其他业务线的写请求,通常都是业务方自己进行业务 ID 的判定,然后投递到历史服务的 BFF 写接口中。最终 BFF 是打包在 app-interface 大杂烩 BFF 中,考虑到隔离性,读写流量很大,独立成 history BFF 服务。 Service(history-service):服务层,去平台业务的逻辑,专注在历史数据的持久化上(因为对于播放类业务,BFF 专注平台业务数据组织,service 负责数据的读、写、删、清理等操作。播放进度是非常高频同步的,需要考虑性能优化)。 使用 write-back 的思路,把状态数据先入分布式缓存,再回写数据库。 Job(history-job):job 消费上游 kafka 的数据,利用消息队列的堆积能力,对于存储层的差速(消费能力跟不上生产速度时),可以进行一定的数据反压。配合上游 service 批量打包过来的数据持久化。 Upstream(some-app,some-api):整个历史服务还会被一些外部 gRPC 服务所依赖,所以 history 还充当了内网的 gRPC Provider,这些上游服务,使用历史服务的写接口,把自己业务的数据进行持久化。 历史服务最重要的设计,就是批量打包(pipeline)聚合数据。将高频、密集的写请求先入缓存(write-back),批量消费减少对存储的直接压力,类似的设计随处可见。 2. history-service history-ser…… 阅读全文

B站架构设计3:评论系统架构设计

2021-08-21 20:37:54

摘要:一、功能设计 架构设计最重要的就是理解整个产品体系在系统中的定位。搞清楚系统背后的背景,才能做出最佳的设计和抽象。不要做需求的翻译机,先理解业务背后的本质,事情的初衷。 评论系统,往小里做就是视频评论系统,往大里做就是评论平台,可以接入各种业务形态。 发布评论:支持回复楼层、楼中楼。 读取评论:按照时间、热度排序。 删除评论:用户删除、作者删除。 管理评论:作者置顶、后台运营管理**(搜索、删除、审核等)**。 在动手设计前,反复思考,真正编码的时间只有10%。 二、架构设计 1. 概述 BFF(comment):复杂评论业务的服务编排,比如访问账号服务进行等级判定,同时需要在 BFF 面向移动端/WEB场景来设计 API,这一层抽象把评论的本身的内容列表处理(加载、分页、排序等)进行了隔离,关注在业务平台化逻辑上。 Service(comment-service):服务层,去平台业务的逻辑,专注在评论功能的 API 实现上,比如发布、读取、删除等,关注在稳定性、可用性上,这样让上游可以灵活组织逻辑把基础能力和业务能力剥离。 Job(comment-job)消息队列的最大用途是消峰处理 Admin(comment-admin):管理平台,按照安全等级划分服务,尤其划分运营平台,他们会共享服务层的存储层(MySQL、Redis)。运营体系的数据大量都是检索,我们使用 canal 进行同步到 ES 中,整个数据的展示都是通过 ES,再通过业务主键更新业务数据层,这样运营端的查询压力就下方给了独立的 fulltext search 系统。 Dependency(account-service、filter-service):整个评论服务还会依赖一些外部 gRPC 服务,统一的平台业务逻辑在 comment BFF 层收敛,这里 account-service 主要是账号服务,filter-service 是敏感词过滤服务。 架构设计等同于数据设计,梳理清楚数据的走向和逻辑。尽量避免环形依赖、数据双向请求等。 2. comment-service comment-service,专注在评论数据处理(认真想下 Separation of Concerns)。 开始是 comment-service 和 comment 是一层,业务耦合和功能耦合在一起,非常不利…… 阅读全文

B站架构设计2:微服务可用性设计

2021-08-14 15:17:22

摘要:一、隔离 隔离,本质上是对系统或资源进行分割,从而实现当系统发生故障时能限定传播范围和影响范围,即发生故障后只有出问题的服务不可用,保证其他服务仍然可用。 服务隔离:动静分离、读写分离 轻重隔离:核心、快慢、热点 物理隔离:线程、进程、集群、机房 1. 服务隔离 动静分离:小到 CPU 的 cacheline false sharing、数据库 mysql 表设计中避免 bufferpool 频繁过期,隔离动静表,大到架构设计中的图片、静态资源等缓存加速。本质上都体现的一样的思路,即加速/缓存访问变换频次小的。 比如 CDN 场景中,将静态资源和动态 API 分离,也是体现了隔离的思路: 降低应用服务器负载,静态文件访问负载全部通过 CDN。 对象存储存储费用最低。 海量存储空间,无需考虑存储架构升级。 静态 CDN 带宽加速,延迟低。 在比如数据库某张表中有些字段是频繁更新的,而另一些很少发生变化。我们就可以把这张表分成2张表来设计: archive: 稿件表,存储稿件的名称、作者、分类、tag、状态等信息,表示稿件的基本信息。 在一个投稿流程中,一旦稿件创建改动的频率比较低。 archive_stat: 稿件统计表,表示稿件的播放、点赞、收藏、投币数量,比较高频的更新。 随着稿件获取流量,稿件被用户所消费,各类计数信息更新比较频繁。 MySQL BufferPool 是用于缓存 DataPage 的,DataPage 可以理解为缓存了表的行,那么如果频繁更新 DataPage 不断会置换,会导致命中率下降的问题,所以我们在表设计中,仍然可以沿用类似的思路,其主表基本更新,在上游 Cache 未命中,透穿到 MySQL,仍然有 BufferPool 的缓存。 读写分离:主从、Replicaset、CQRS。 2. 轻重隔离 核心隔离:业务按照 Level 进行资源池划分(L0/L1/L2)。 核心/非核心的故障域的差异隔离(机器资源、依赖资源)。 多集群,通过冗余资源来提升吞吐和容灾能力。 快慢隔离:我们可以把服务的吞吐想象为一个池,当突然洪流进来时,池子需要一定时间才能排放完,这时候其他支流在池子里待的时间取决于前面的排放能力,耗时就会增高,对小请求产生影响。 日志传输体系的架构设计中,整个流都会投放到一个 …… 阅读全文

B站架构设计1:微服务概览与治理

2021-08-07 12:22:49

摘要:一、微服务概述 1. 单体架构 尽管也是模块化逻辑,但是最终它还是会打包并部署为单体式应用。其中最主要问题就是这个应用太复杂,以至于任何单个开发者都不可能搞懂它。应用无法扩展,可靠性很低,最终,敏捷性开发和部署变的无法完成。 我们应对的思路:化繁为简,分而治之 2. 微服务起源 大家经常谈论的是一个叫 SOA(面向服务的架构模式),它和微服务又是什么关系?你可以把微服务想成是 SOA 的一种实践。 小即是美:小的服务代码少,bug 也少,易测试,易维护,也更容易不断迭代完善的精致进而美妙。 单一职责:一个服务也只需要做好一件事,专注才能做好。 尽可能早地创建原型:尽可能早的提供服务 API,建立服务契约,达成服务间沟通的一致性约定,至于实现和完善可以慢慢再做。 可移植性比效率更重要:服务间的轻量级交互协议在效率和可移植性二者间,首要依然考虑兼容性和移植性。 3. 微服务定义 围绕业务功能构建的,服务关注单一业务,服务间采用轻量级的通信机制,可以全自动独立部署,可以使用不同的编程语言和数据存储技术。微服务架构通过业务拆分实现服务组件化,通过组件组合快速开发系统,业务单一的服务组件又可以独立部署,使得整个系统变得清晰灵活: 原子服务 独立进程 隔离部署 去中心化服务治理 缺点:基础设施的建设、复杂度高 4. 微服务的不足 Fred Brooks 在30年前写道,“there are no silver bullets”。但凡事有利就有弊,微服务也不是万能的。 微服务应用是分布式系统,由此会带来固有的复杂性。开发者不得不使用 RPC 或者消息传递来实现进程间通信;此外,必须要写代码来处理消息传递中速度过慢或者服务不可用等局部失效问题。 分区的数据库架构,同时更新多个业务主体的事务很普遍。这种事务对于单体式应用来说很容易,因为只有一个数据库。在微服务架构应用中,需要更新不同服务所使用的不同的数据库,从而对开发者提出了更高的要求和挑战。 测试一个基于微服务架构的应用也是很复杂的任务。 服务模块间的依赖,应用的升级有可能会波及多个服务模块的修改。 对运维基础设施的挑战比较大。 5. 组件服务化 传统实现组件的方式是通过库(library),库是和应用一起运行在进程中,库的局部变化意味着整个应用的重新部署。 通过服务来实现组件,意味着将应用拆散为一系列的服务运行在…… 阅读全文

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能够跟…… 阅读全文

架构师的计算机基础1

2018-11-05 12:34:08

摘要:CPU是什么 我们都知道的定义是这样的:CPU又称中央处理器,它的英文全称为:Central Processing Unit,但同时如果你听到:Central Processor或者Main Processor往往同样也指的是CPU。 普通程序员开发的程序,其实绝大多数指的就是对中央处理器也就是CPU的编程。这句话也可能会被面试人员反着描述为,计算机的可编程性主要是指对中央处理器的编程。 在最初的时候,大约是1970年代以前,中央处理器由多个独立单元构成,后来才发展成集成电路,这些高度收缩的组件就是所谓的:微处理器。 另外,中央处理器广义上来说,是可以指代一系列可以执行复杂的计算机程序的逻辑机器。还记得三体中秦始皇嬴政派出无数士兵进行逻辑与或非运算吗?那样的场景,其实就是实现了广义上的中央处理器。 注意:ENIAC(Electronic Numerical Integrator And Computer)是世界上第一台”电子存储式可编程计算机”,但是由于他们也存在计算功能,而CPU的标准定义为:执行软件(计算机程序)的设备所以,ENIAC理论上不存在标准的CPU,但是最早于存储程序型计算机一通登场的设备是可以被称作CPU的,也就是说:CPU并不一定是微型的,早起的同步CPU是非常大的。直到1950~60年代的晶体管CPU时,CPU才慢慢变小。不再以体积庞大,不可靠与易碎的开关组件(继电器/真空管)组成或建造。 参考来自于维基百科,与哈佛计算机原理书籍,国内的一些小众参考资料与翻译是错误的,一定要注意。CPU并不小。尤其是百度百科,它所提供的参考资料只提及了”微”,但是万物相对论,没有相对何来形容词?从本段落开始,咱们只讨论:冯·诺依曼机,不讨论哈佛架构。 CPU的主要运作原理 CPU的主要运作原理很简单。不论其外观,都是执行存储与被称为”程序”里的一系列指令。所以说计算机是最愚蠢的傻子,没有码农他们就是一坨铁。 在冯诺依曼架构中,程序以一系列数字存储在计算机存储器中。 而只要是冯诺依曼机,CPU的运作原理就可以看成四个阶段:提取,解码,执行,回写。 提取:从程序内存中检索指令(程序内存,指的可不是你程序里面定义了一个int的这个内存,而是存储程序的内存),由程序计数器指定程序存储器的位置,计数器保存供识别当前程序位置的数值(原始资料原文)。 拿人话说:程序计数…… 阅读全文

微服务架构(九):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.…… 阅读全文