【转载】单点系统架构的可用性与性能优化

【转载】单点系统架构的可用性与性能优化

一、需求缘起

明明架构要求高可用,为何系统中还会存在单点?

回答:单点master的设计,会大大简化系统设计,何况有时候避免不了单点

在哪些场景中会存在单点?先来看一下一个典型互联网高可用架构。

0a46823d9bcfa6e7b7348b96deab0ece
典型互联网高可用架构:

(1)客户端层,这一层是浏览器或者APP,第一步先访问DNS-server,由域名拿到nginx的外网IP

(2)负载均衡层,nginx是整个服务端的入口,负责反向代理与负载均衡工作

(3)站点层,web-server层,典型的是tomcat或者apache

(4)服务层,service层,典型的是dubbo或者thrift等提供RPC调用的后端服务

(5)数据层,包含cache和db,典型的是主从复制读写分离的db架构

在这个互联网架构中,站点层、服务层、数据库的从库都可以通过冗余的方式来保证高可用,但至少

(1)nginx层是一个潜在的单点

(2)数据库写库master也是一个潜在的单点

再举一个GFS(Google File System)架构的例子。

d559a36b6e135c00cedb91d68c41438d
GFS的系统架构里主要有这么几种角色:

(1)client,就是发起文件读写的调用端

(2)master,这是一个单点服务,它有全局事业,掌握文件元信息

(3)chunk-server,实际存储文件额服务器

这个系统里,master也是一个单点的服务,Map-reduce系统里也有类似的全局协调的master单点角色。

系统架构设计中,像nginx,db-master,gfs-master这样的单点服务,会存在什么问题,有什么方案来优化呢,这是本文要讨论的问题。

 

二、单点架构存在的问题

单点系统一般来说存在两个很大的问题:

(1)非高可用:既然是单点,master一旦发生故障,服务就会受到影响

(2)性能瓶颈:既然是单点,不具备良好的扩展性,服务性能总有一个上限,这个单点的性能上限往往就是整个系统的性能上限

接下来,就看看有什么优化手段可以优化上面提到的两个问题

 

三、shadow-master解决单点高可用问题

shadow-master是一种很常见的解决单点高可用问题的技术方案。

“影子master”,顾名思义,服务正常时,它只是单点master的一个影子,在master出现故障时,shadow-master会自动变成master,继续提供服务。

shadow-master它能够解决高可用的问题,并且故障的转移是自动的,不需要人工介入,但不足是它使服务资源的利用率降为了50%,业内经常使用keepalived+vip的方式实现这类单点的高可用

f79d04135838d00b1e0be66770875850
以GFS的master为例,master正常时:

(1)client会连接正常的master,shadow-master不对外提供服务

(2)master与shadow-master之间有一种存活探测机制

(3)master与shadow-master有相同的虚IP(virtual-IP)

e7d7afb6115502c814b0555659fb6524
当发现master异常时:

shadow-master会自动顶上成为master,虚IP机制可以保证这个过程对调用方是透明的

除了GFS与MapReduce系统中的主控master,nginx亦可用类似的方式保证高可用,数据库的主库master(主库)亦可用类似的方式来保证高可用,只是细节上有些地方要注意:

c409d0fc5caaafc0309690c6b2c17b54
传统的一主多从,读写分离的db架构,只能保证读库的高可用,是无法保证写库的高可用的,要想保证写库的高可用,也可以使用上述的shadow-master机制:

8f7921ecabf078fc0d85cd2ba67eae7c
(1)两个主库设置相互同步的双主模式

(2)平时只有一个主库提供服务,言下之意,shadow-master不会往master同步数据

(3)异常时,虚IP漂移到另一个主库,shadow-master变成主库继续提供服务

需要说明的是,由于数据库的特殊性,数据同步需要时延,如果数据还没有同步完成,流量就切到了shadow-master,可能引起小部分数据的不一致。

 

四、减少与单点的交互,是存在单点的系统优化的核心方向

既然知道单点存在性能上限,单点的性能(例如GFS中的master)有可能成为系统的瓶颈,那么,减少与单点的交互,便成了存在单点的系统优化的核心方向。

怎么来减少与单点的交互,这里提两种常见的方法。

批量写

批量写是一种常见的提升单点性能的方式。

例如一个利用数据库写单点生成做“ID生成器”的例子:

3e910109ca3ef7a65dda7d7c80924949
(1)业务方需要ID

(2)利用数据库写单点的auto increament id来生成和返回ID

这是一个很常见的例子,很多公司也就是这么生成ID的,它利用了数据库写单点的特性,方便快捷,无额外开发成本,是一个非常帅气的方案。

潜在的问题是:生成ID的并发上限,取决于单点数据库的写性能上限。

如何提升性能呢?批量写

11d4ee7fa9151c45b9ab69eaf73fe9a8
(1)中间加一个服务,每次从数据库拿出100个id

(2)业务方需要ID

(3)服务直接返回100个id中的1个,100个分配完,再访问数据库

这样一来,每分配100个才会写数据库一次,分配id的性能可以认为提升了100倍。

客户端缓存

客户端缓存也是一种降低与单点交互次数,提升系统整体性能的方法。

还是以GFS文件系统为例:

a53534789a48fee406189caf786d2848
(1)GFS的调用客户端client要访问shenjian.txt,先查询本地缓存,miss了

(2)client访问master问说文件在哪里,master告诉client在chunk3上

(3)client把shenjian.txt存放在chunk3上记录到本地的缓存,然后进行文件的读写操作

(4)未来client要访问文件,从本地缓存中查找到对应的记录,就不用再请求master了,可以直接访问chunk-server。如果文件发生了转移,chunk3返回client说“文件不在我这儿了”,client再访问master,询问文件所在的服务器。

根据经验,这类缓存的命中非常非常高,可能在99.9%以上(因为文件的自动迁移是小概率事件),这样与master的交互次数就降低了1000倍。

 

五、水平扩展是提升单点系统性能的好方案

无论怎么批量写,客户端缓存,单点毕竟是单机,还是有性能上限的。

想方设法水平扩展,消除系统单点,理论上才能够无限的提升系统系统。

以nginx为例,如何来进行水平扩展呢?

07414070ed817c2145b37d6363dbe2fc
第一步的DNS解析,只能返回一个nginx外网IP么?答案显然是否定的,“DNS轮询”技术支持DNS-server返回不同的nginx外网IP,这样就能实现nginx负载均衡层的水平扩展。

0edbd3081cc179fd8195375fb4e10845
DNS-server部分,一个域名可以配置多个IP,每次DNS解析请求,轮询返回不同的IP,就能实现nginx的水平扩展,扩充负载均衡层的整体性能。

数据库单点写库也是同样的道理,在数据量很大的情况下,可以通过水平拆分,来提升写入性能。

遗憾的是,并不是所有的业务场景都可以水平拆分,例如秒杀业务,商品的条数可能不多,数据库的数据量不大,就不能通过水平拆分来提升秒杀系统的整体写性能(总不能一个库100条记录吧?)。

 

六、总结

今天的话题就讨论到这里,内容很多,占用大家宝贵的时间深表内疚,估计大部分都记不住,至少记住这几个点吧:

(1)单点系统存在的问题:可用性问题,性能瓶颈问题

(2)shadow-master是一种常见的解决单点系统可用性问题的方案

(3)减少与单点的交互,是存在单点的系统优化的核心方向,常见方法有批量写,客户端缓存

(4)水平扩展也是提升单点系统性能的好方案

如果有收获,帮忙随手转发哟。

==【完】==

 

【转自】58沈剑 架构师之路

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/119381.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 初始java数组_初始化数组为0

    初始java数组_初始化数组为01.初始化定义2.数组的三种打印方式3.数组引用null4.浅谈引用变量的影响5.与数组相关的字符串操作以及javaJVM内存简单介绍6.浅谈二维数组与C的区别

    2022年10月21日
  • 毕业六年

    今年工作变化。这一年可以说命途多舛,下半年短短几个月,换了3条业务4个老板,有被动调整,也有主动转岗,面临比较重要的选择,还是相当煎熬的。这个过程有些坑,空了单独分享。运气不好的是频繁拥抱变化,有些努力白费了,意外之中又有意外,不过运气好的是年终没吃太多亏,权当是走个弯路,浪费了一年时间吧。惰性。技术上来说,转后端一年多,工作够用了,不过这两年从客户端折腾到前端又到后端,把技术热情磨没了,可能也是各方面原因,今年第一次感觉到了惰性,有点佛,感觉够用就行,不再试图知其所以然…

  • IE Flash10b.ocx加载项失败 解决

    IE Flash10b.ocx加载项失败 解决在做一个页面的视频录制时,预览页面时,总会提示Flash10b.ocx加载项失败,导致IE被迫关闭,很是恼火。在网上搜了下,原来是原来是AdobeFlashplayer控件出的问题,10.0的版

  • 计算机按位取反[通俗易懂]

    计算机按位取反[通俗易懂]取反过程1.转成二进制2.取补码3.补码的反码(符号位不变)4.反码加+1可以通过原码、反码和补码三者的含义及关系来介绍三者之间的换算关系:1、原码原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值。比如如果是8位二进制:[+1]原=00000001[-1]原=10000001第一位是符号位。2、反码

  • centos随机生成密码

    centos随机生成密码要安装expectyum-yinstallexpect安装完成就可以使用常用参数-l#(密码的长度定义,默认是9)-d#(数字个数,默认是2)-c#(小写字符,默认是3)-C#(大写字符,默认是2)-s#(特殊字符,默认是1)例如:[root@localhost~]#mkpasswd-l10-d2-C2-s1Bxk_e.

    2022年10月23日
  • UpdatePanel简单用法

    UpdatePanel简单用法ScriptManager和UpdatePanel控件联合使用可以实现页面异步局部更新的效果。其中的UpdatePanel就是设置页面中异步局部更新区域,它必须依赖于ScriptManager存在,因为ScriptManger控件提供了客户端脚本生成与管理UpdatePanel的功能。几个重要的属性:   ScriptManager控件的EnablePartialRendering属性:t

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号