消除单点,一篇搞定 | 架构设计篇
系统架构中,为什么会存在单点?
(1)存在设计缺陷,出现了单点;
(2)能大大简化系统设计,有意为之,设置单点;
典型互联网高可用架构,哪些地方可能存在潜在单点?
典型互联网高可用架构:
(1)端,通过DNS,由域名拿到nginx的外网IP;
(2)反向代理,nginx是后端入口;
(3)站点应用,典型的是tomcat或者apache;
(4)服务,典型的是dubbo提供RPC服务调用;
(5)数据层,典型的是读写分离的db架构;
在这个互联网架构中,站点、服务、数据库的从库都容易通过冗余的方式来保证高可用,但:
(1)nginx是一个潜在的单点;
(2)数据库写库也是一个潜在的单点;
哪些例子,因为设计需要,有意设置的单点?
先看GFS(Google File System)架构的例子:
(1)client,就是发起文件读写的调用端;
(2)master,这是一个单点服务,它有全局视野,掌握文件元信息;
(3)chunk-server,实际存储文件的服务器;
在GFS系统里,master是一个单点服务。
Map-reduce系统里也有类似的角色,协调全局的master就是单点,它的存在,能够大大的简化系统架构设计。
不管是设计缺陷,还是有意为之,像nginx,db-master,GFS-master这样的单点服务,会存在什么问题呢?
两个大问题:
(1)高可用问题:单点一旦发生故障,服务就会受到影响;
(2)性能瓶颈:单点不具备良好的扩展性,单点的性能上限往往就是整个系统的性能上限;
“高可用”问题通常怎么优化?
shadow-master是一种很常见的解决单点高可用问题的技术方案。
shadow-master,顾名思义,它只是单点master的一个shadow(影子):
(1)master工作时,shadow-master只备份;
(2)master出现故障时,shadow-master会自动变成master,继续提供服务;
shadow-master它能够解决高可用的问题,并且故障的转移是自动的,不需要人工介入,但不足是它使资源的利用率降为了50%,业内经常使用keepalived+vip的方式实现这类单点的高可用。
(1)client会连接正常的master,shadow-master不对外提供服务;
(2)master与shadow-master之间有一种存活探测机制;
(3)master与shadow-master有相同的虚IP;
当发现master异常时:
shadow-master会自动顶上成为master,虚IP机制可以保证这个过程对调用方是透明的。
除了GFS与MapReduce系统中的主控master,nginx和数据库的主库master亦可用类似的方式来保证高可用:
(2)平时只有一个主库提供服务;
(3)异常时,虚IP漂移到另一个主库,shadow-master变成主库继续提供服务;
关于高可用,更多详细的内容,可参考《究竟啥才是互联网架构“高可用”》。
“性能瓶颈”问题通常怎么优化?
有时候,单点设计是有意为之,此时单点的性能(例如GFS中的master)有可能成为系统的瓶颈,那么,减少与单点的交互,便成了存在单点的系统优化的核心方向。
如何来减少与单点的交互,有两种常见的方法:
(1)批量写;
(2)客户端缓存;
如何利用“批量写”减少与单点的交互,提升整体性能?
举一个单点“ID生成器”的例子,很多公司会利用数据库的auto-inc-id,来作为一个严格递增的ID生成工具。
(1)调用方需要ID;
(2)插入记录,利用auto-inc-id来生成和返回ID;
此时,ID生成的并发上限,取决于单点数据库的插入性能上限。
如何利用“批量写”提升性能呢?
优化如下:
(1)增加一个服务,每次从DB拿出100个id;
(2)调用方需要ID;
(3)服务直接返回100个id中的1个,100个分配完,再访问DB;
这样一来,每分配100个才会写数据库一次,分配id的性能提升了100倍。
如何利用“客户端缓存”减少与单点的交互,提升整体性能?
还是举GFS文件系统的栗子。
(1)GFS的调用客户端client要访问shenjian.txt,先查询本地缓存,miss了;
(2)client访问master问说文件在哪里,master告诉client在chunk3上;
(3)client把shenjian.txt存放在chunk3上记录到本地的缓存,然后进行文件的读写操作;
(4)未来client要访问文件,从本地缓存中查找到对应的记录,就不用再请求master了,可以直接访问chunk-server;
这类缓存的命中非常非常高,在99%以上(因为文件的自动迁移是小概率事件),这样与master的交互次数就降低了100倍。
批量写,客户端缓存,对性能的提升也有极限,单点性能优化还有没有其他方法?
无论怎么批量写,客户端缓存,单点毕竟是单机,还是有性能上限的。
水平扩展,才能够无限的提升系统性能。
以nginx为例,如何来进行水平扩展呢?
通过DNS轮询,在DNS-server,一个域名可以配置多个IP,每次DNS解析请求,轮询返回不同的IP,就能实现nginx的水平扩展,扩充负载均衡层的整体性能。
数据库单点写库也是同样的道理,在数据量很大的情况下,可以通过水平拆分,来提升写入性能。
关于性能扩展,更多详细的内容,可参考《究竟啥才是互联网架构“可扩展”》。
总结
今天的内容很多,希望行文有逻辑:
(1)单点系统存在的问题:可用性问题,性能瓶颈问题;
(2)shadow-master是一种常见高可用方案;
(3)减少与单点的交互,是单点系统优化的核心方向,常见方法有:批量写,客户端缓存;
(4)水平扩展,才能做到理论上的无限性能;
思路比结论重要。
原文发布时间为:2018-11-01
本文作者:58沈剑

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
分享我如何在7年时间里成长为阿里Java架构师(附学习路线图)
如何更高效的学习? 1.架构师应不应该写代码 合格的程序员对于明确分配的任务会完成的很好,但是大部分情况下“架构”这个词意味着架构师并不会涉及太多细节,架构图和代码实现之间总还是有些距离,你无法保证所有人都会正确的理解你的设计,或者是程序员写代码时遇到障碍时会立刻想出足够优雅的解决方案。 在我看来,写代码的架构师更像是在做后勤保障的工作:在代码中第一时间发现可能存在的问题,向其他人提出警告,或是给予其他人改进的意见,必要的时候或是给其他人演示一下正确的姿势。 大部分情况下我作为架构师并不需要揽下“核心模块”开发这种工作,毕竟我能调配的时间太零散了,效率难以保证,很多人在专注的情况下比我做的好很多,我只需要保持大局观需要适度参与就可以了。 总的来说,架构师和程序员在某些方面上有点像产品经理和用户的关系,大部分程序员并不会主动告诉你他们想要什么、哪里需要优化,甚至自己也不知道这些。想要做出好的产品,捷径之一就是跟用户做同样的事情。 2.为什么别人的系统总是那么烂 很多程序员解决问题的能力很强,说要解决一个什么问题,下午就能写出几百行代码把功能实现了。但是做出来的东西有种少考虑了什么东西的感...
- 下一篇
使用函数 initializer 接口优化应用层冷启动
背景 用户函数调用链路包括以下几个阶段:1)系统为函数分配计算资源;2)下载代码;3)启动容器并加载函数代码;4)用户函数内部进行初始化逻辑;5)函数处理请求并将结果返回。其中1,2,3步是系统层面的冷启动开销,通过对调度以及各个环节的优化,函数计算(FC)能做到负载快速增长时稳定的延时,细节详见 函数计算系统冷启动优化。第4步是函数内部初始化逻辑,属于应用层面的冷启动开销,例如深度学习场景下加载规格较大的模型、数据库场景下连接池构建、函数依赖库加载等等。为了减小应用层冷启动对延时的影响,函数计算推出了 initializer 接口,系统能识别用户函数的初始化逻辑,从而在调度上做相应的优化。 功能简介 现在用户能为函数设置 initializer 和 handler 两个入口,分别对应初始化逻辑和请求处理逻辑。系统首先调用 initia
相关文章
文章评论
共有0条评论来说两句吧...