《高可用架构第1卷【2】》——高可用架构原理与分布式实践

 

《高可用架构第1卷【1】》css

http://www.noobyard.com/article/p-ytshkmyz-by.htmlhtml

 

《高可用架构第1卷【2】》前端

 

麦俊生/1.6 亿级短视频社交美拍架构实战59
1.6.1 短视频市场的发展59
1.6.2 美拍的发展.60
1.6.3 短视频所面临的架构问题61
1.6.4 为支持亿级用户,美拍架构所作的一些改进62
1.6.5 后续发展68java

[转载] 亿级短视频社交美拍架构实战 - 云栖社区 - 阿里云1、短视频市场的发展 近几年来,短视频应用在国内应用市场引爆,美图公司推出了美拍,相关的产品还有 GIF 快手、秒拍、微视、逗拍、玩拍等,一系列短视频产品的出现也丰富了短视频应用市场。

1、短视频市场的发展

近几年来,短视频应用在国内应用市场引爆,美图公司推出了美拍,相关的产品还有 GIF 快手、秒拍、微视、逗拍、玩拍等,一系列短视频产品的出现也丰富了短视频应用市场。node

短视频的相继爆发,与几个因素有关:python

一、带宽,随着中国基础网络环境的发展,愈来愈多的 2G 移动网民开始转向使用 3G/4G 网络,从而体验到更好的上传下载带宽和更稳定的网络, 目前 3G/4G 的移动用户比例大概占比 85% 以上;同时随着资费的进一步下降,月户平均流量也达到了 360M,甚至很多部分是 GB 甚至几十 GB 的级别的流量,因此就一个普通的 10s 视频而言大概不到 1~2M 甚至几百 K,带宽流量的提高无疑会逐步下降用户使用的门槛;此外,家用带宽也随之增长,目前 10M 甚至 100M ` 已经成为家用带宽的主流,从而为短视频的发展提供了必要条件。mysql

二、手机硬件配置的极大改进,随着像素的增长、手机硬件配置 CPU、GPU、内存等的升级,可以让手机更快的来处理和优化视频效果,从而可以给手机视频的处理带来更多的创意空间。react

三、传统的文字和图片的表达能力不够丰富,因此没法知足网民的需求,而短视频带来了足够大的表现空间。nginx

四、产品自己,提供了各类方式来下降用户视频的制做门槛,好比美拍提供了 MV 特效等,来提高了制做视频的趣味性的同时,下降使用的门槛。同时产品的多样化,也知足了各类用户的差别化需求,激发用户自传播。git

2、美拍的发展

美拍在 2014.05 月发布,上线仅 1 天,即登入 App Store 免费总榜第一,当月下载量排名第一。在发布 9 个月的时候,用户就突破 1 个亿。目前天天美拍视频日播放量在 2.7 亿以上,日视频播放时长达到 183 万小时。

面临这种用户量爆发的增加,美拍也遇到了不少应用起步之初那些年所遇到的甜蜜和苦涩的回忆,通过 1 年多的架构的演进,美拍也积累了必定的经验,造成了一套高可用高可扩展的架构实践。虽没法作到很华丽,却会随着架构的不断的演进而不断的完善。

相比于普通的文本社交类 APP,作这么一个短视频产品在技术架构层面,会面临哪些问题呢?

 

 

 


 

和通用的文本社交类产品同样,美拍有首页热门、好友动态(feed 流)、评论服务、私信服务等基础功能;因此在用户爆发增加后,一样会面临应用层、数据库、缓存、接入层等方面的挑战,那么如何作到低延迟、高可用呢。同时由于是短视频自己,也会面临一些特定的领域性相关的问题。

3、短视频所面临的架构问题

短视频相比于文本数据而言,有着一些差别:

一、数据大小的差别

好比一条美拍,通过视频压缩和清晰度的权衡,10s 的视频大小 1MB 多,而一条 5 分钟视频的美拍甚至要达到几十 M,相比与几十字节或者几百字节的文本要大得多。由于数据量要大得多,因此也会面临一些问题:如何上传、如何存放、以及如何播放的问题。

关于上传,要在手机上传这么一个视频,特别是弱网环境要上传这么一个文件,上传的成功率会比较低,晚高峰的时候,省际网络的拥塞状况下,要更为明显得多。因此针对上传,须要基于 CDN 走动态加速来优化网络链路(经过基调实测过对于提高稳定性和速度有必定帮助),同时对于比较大的视频须要作好分片上传,减小失败重传的成本和失败几率等来提高可用性。同时不一样 CDN 厂商的链路情况在不一样的运营商不一样地区可能表现不一,因此也须要结合基调测试,选择一些比较适合本身的 CDN 厂商链路

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

所谓的 CDN 动态加速技术

原标题:所谓的 CDN 动态加速技术

之前说 CDN 的优点是其在网络边缘缓存了用户请求的内容,离用户近,从而保证用户的访问效果; 可是动态网页因为是源站动态生成的内容,CDN 的边缘节点没法存储用户请求的内容,请求到了边缘节点以后还得回源,传统 CDN 架构上的优点就没有了。那么 cdn 动态加速尚未价值? 首先让咱们看看 cdn 动态加速技术是怎么样的:

让咱们看如下公式:

用户请求耗费的时间 = 用户和边缘交互的时间 + 边缘等待的时间;

其中用户和边缘交互的时间,咱们能够看作用户向边缘请求一个静态文件的时间,边缘等待时间,是用户请求到了之后,边缘须要向用户发送数据,确没有数据能够发送,等他数据到达的这段时间; CDN 动态加速技术的本质主要是要减小第二部分的时间;

首先咱们说,经过网络优化和协议优化,咱们能够容易的把上面那个公式变成下式:

用户请求耗费的时间 = 用户和边缘交互的时间 + 1*RTT(边缘到源站)+ 源站的反应时间;

让咱们忽略掉源站的反应时间,由于他和咱们今天讨论的动态加速没有关系,咱们能够把它看作一个常量;

Ok,让咱们看看,这是怎么作到的,首先让咱们看看,不优化的时候是个什么状况,如图 1 所示,最坏状况下边缘等待的时间 = 创建链接的时间 (1*RTT)+ 发送请求的时间 (1*RTT)+ 数据传输中的等待时间。

 

 

其中经过优化咱们能够把创建链接的时间消灭掉,有两种发送能够作到这一点:

1. 经过链接复用,保证每次动态请求到达时,边缘和源之间的通路,链接都已经创建了,它的弊端是在突发状况下很难保证;

2. 经过 TCP 协议栈的定制,把链接和请求的过程合并起来,这事咱们在 09 年就一直在说,只不过因为种种缘由没有作下去,听说 google 已经作出来了;

除此之外咱们还能够把数据传输开始之后的等待时间给去除掉,这里面涉及到了两个技术,一个是动态路由,一个是 TCP 协议优化;

动态路由:所谓动态路由,指的是利用 CDN 节点多的优点,把每一个节点都看作一个路由,在边缘 A 和源 B 之间找到一个最佳路径,也就是说之前是直接从 A 到 B,变成了 A-C-D-B; 另外还须要强调的是,D-B 之间必定是要经过链接创建,并且 D-B 必定要很近,时延很小,不然的话 TCP 协议优化就发挥不了做用; 经过动态路由技术咱们能够在 A-B 间创建一个更低的 RTT 和更小的丢包率的经过; 网络调度规划问题

节点间的 TCP 协议优化:有了动态路由作保证,节点间的 TCP 协议优化就是很简单的事情了,咱们要知道用户的带宽每每是有限的,而节点间的带宽每每是冗余的,咱们要作到节点间的发送速率高于边缘到用户是很是容易的,改几行代码就够了;

经过以上一些技术咱们就能够把图 1 精简成图 2:

 

 

这还不够,咱们能不能把这一个时延也去掉呢,这是部分可能的,这里面涉及到了一下一些技术:

1. 缓存,部分的动态内容也是能够在很短的时间内缓存的;

2. 预取:经过用户请求的页面内容解析,预先感知用户接下来要获取的内容,提早预取;

3. 在边缘生成用户请求的内容,这个水太深,我说不清楚,点到为止;

4. 证书类:经过在边缘部署 SSL 证书,在边缘将 SSL 请求,变成普通请求,从而将动态加速变成静态加速,可是如此是有风险的,把 CDN 运营商当作安全是不安全的;

除了以上一些技术之外,我还漏了一个,那就是压缩,压缩分红两部分,一部分是 http 头支持的压缩,这些就不要让 CDN 帮你干了,源站应该本身作的; 另外一部分是 CDN 节点间的,如此能够减小 CDN 节点间传递的数据量,从而变向加快传输速度; 可是这里会增长机器的 CPU 负载,同时,有了 TCP 协议优化技术,不须要经过压缩来提升传输速度,因此我的认为它不重要。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

同时由于数据相对比较大,当数据量达到必定规模,存储容量会面临一些挑战,目前美拍的视频容量级别也达到 PB 级别的规模,因此要求存储自己可以具有比较强的线性扩展能力,而且有足够的资源冗余,而传统的 MySQL 等数据库比较难来支持这个场景,因此每每须要借助于专用的分布式对象存储。能够经过自建的服务或者云存储服务来解决。得益于近几年云存储的发展,目前美拍主要仍是使用云存储服务来解决。自身的分布式对象存储主要用于解决一些内部场景,好比对于数据隐私性和安全性要求比较高的场景。

播放方面,由于文件比较大,也容易受到网络的影响,因此为了规避卡顿,一些细节也须要处理。好比对于 60s,300s 的视频,须要考虑到文件比较大,同时有拖动的需求,因此通常使用 http range 的方式,或者基于 HLS 的点播播放方式,基于前者比较简单粗暴,不过基于播放器的机制,也可以知足需求,也能实现点播拖动。而直接基于 HLS 的方式会更友好,特别是更长的一些视频,好比 5 分钟甚至更大的视频,不过这种须要单独的转码支持。以前美拍主要是短视频为主,因此更多使用 http range 的方式。然后续随着 5 分钟或者更大视频的场景,也在逐步作一些尝试。同时对于播放而言,在弱网环境下,可能也会面临一些问题,好比播放时卡顿的问题,这种通常经过网络链路优化;或者经过多码率的自适应优化,好比多路转码,而后根据特定算法模型量化用户网络状况进行选码率,网络差的用低码率的方式

二、数据的格式标准差别

相比于文本数据,短视频自己是二进制数据,有比较固定的编码标准,好比 H.26四、H.265 等,有着比较固定和通用的一些格式标准。

三、数据的处理需求

视频自己可以承载的信息比较多,因此会面临有大量的数据处理需求,好比水印、帧缩略图、转码等。而视频处理的操做是很是慢的,会带来巨大的资源开销。

美拍对于视频的处理,主要分为两块:

客户端处理,视频处理尽可能往客户端靠,利用现有强大的手机处理性能来减小服务器压力, 同时这也会面临一些低端机型的处理效率问题,不过特别低端的机型用于上传美拍自己比较少数,因此问题不算明显。客户端主要是对于视频的效果叠加、人脸识别和各类美颜美化算法的处理,咱们这边客户端有实验室团队,在专门作这种效果算法的优化工做。同时客户端处理还会增长一些必要的转码和水印的视频处理。目前客户端的视频编解码方式,会有软编码和硬编码的方式,软编码主要是兼容性比较好,编码效果好些,不过缺点就是能耗高且慢些。而硬编码借助于显卡等,可以获得比较低的能耗而且更快,不过兼容和效果要差一些,特别是对于一些低配的机型。因此目前每每采用结合的方式

服务端的处理,主要是进行视频的一些审核转码工做,也有一些抽帧生成截图的工做等,目前使用 ffmpeg 进行一些处理。服务端自己须要考虑的一些点,就是由于资源消耗比较高,因此须要机器数会更多,因此在服务端作的视频处理操做,会尽可能控制在一个合理的范围。同时由于美拍这种场景,也会遇到这些热点事件的突变峰值,因此转码服务集群自己须要具有可弹性伸缩和异步化消峰机制,以便来适应这种突增请求的场景。

4、为支持亿级用户,美拍架构所作的一些改进

随着用户和访问量的快速增加,美拍遇到很多的挑战

  • 性能的挑战

  • 可用性的挑战

  • 突发热点的挑战

  • 业务频繁迭代的挑战

在频繁的业务迭代的状况下,如何可以在海量请求下保证足够高的可用性,同时以一个比较好的用户体验和比较低的成本的方式来提供服务成为咱们努力的方向。

这个是目前美拍的总体架构全貌

 

 

 


 

这一个架构目前也正在不断的持续演进的过程当中,除了一些基础服务组件的建设外,咱们还着重在服务治理作一些相关工做,来保证总体服务的可用和稳定。

 

 

 


 

分而治之、化繁为简

规划总体架构,明确服务模块的单一职责,尽可能保持足够内聚,而服务模块之间作到解耦,这样就可以针对单一模块进行更精细化的优化工做,同时可以用适合的技术来解决适合的场景问题。

服务之间的交互和通信,咱们主要走了两种方式:

  • 基于 HTTP 的方式

  • 基于 config service + RPC 的方式

前者使用的方式比较简单,目前咱们主要在跨团队、跨语言(好比 PHP 和 golang 之类的)会使用,主要会在七层 nginx 层作一些工做,如负载均衡、节点探测、并发保护等。

 

 

 


 

而第二种方式,咱们主要用于内部系统之间的一些交互。目前咱们主要基于 etcd 来实现咱们的动态服务发现和配置服务,在 client 层面扩展实现了包含负载均衡、心跳、节点健康状态探测、etcd 节点挂掉的灾备等基础功能,同时会经过一些 metrics 埋点,以便跟踪内部的状态,用统一的 trace_id 来跟踪服务的链路调用状况。

 

 

 


 

开放扩展

主要针对下面几个点:

  • 代码功能的可扩展性

  • 交互协议的扩展性

  • 数据存储格式的可扩展性

  • 应用的可扩展性

  • 资源的可扩展性

交互协议,既针对交互接口,也针对 app 客户端和服务端的交互协议。特色是 app 客户端和服务端的交互协议,由于 app 的升级较之服务端升级的时间久得多,好比你发布了一个客户端版本 V0.1,若是用户后面一直不升级,这个时间多是几个月、半年甚至一年,那么就会引入一些兼容问题,因此在协议层面设计的关键点须要考虑这种状况的存在,须要保证协议可以向前兼容,预留好扩展点。

而关于数据存储格式的可扩展性,美拍第一个版本每一个属性在数据库中为一个字段,而且为了保持必定的扩展性也多加了几个扩展字段。在发展过程当中演化为全部属性字段序列化为 protocol buffer 数据的方式,这样能更好知足快速发展的业务需求。可是你们每每也更多关注在服务端,其实有时候比较坑的是在客户端。以前就踩过坑客户端上有个 id 字段的数据类型使用 int32,由于客户端基本很难作强升,一个这样小的事情最终须要很长时间来消化解决,而且为此还须要作一些兼容工做。因此针对这类事情,建议你们在一开始时候也多留意,尽可能少为未来埋坑。

分级隔离

目前咱们主要经过这几个维度进行一些隔离:

  • 核心和非核心的隔离

  • 单一集群的内部隔离

  • 不一样集群的外部物理资源隔离

  • 不一样集群的外部依赖资源的隔离

 

 

 


 

美拍在发展早期,跟多数发展早期的系统同样,也是多数接口部署在同一个集群中,包括也共用了一些资源(好比 memcached ),这样的好处是早期部署上足够的简单。在发展的过程当中,业务在快速发展,业务复杂度也在逐步提高,接口调用量也急剧增长,逐步就暴露出一些问题。美拍的发展过程也是实际的去验证了前面提到的分级隔离机制。

在发展早期,曾经有个调用量不小的非核心的业务,在对存储数据结构作了调整后的上线过程当中出现性能问题,致使整个集群服务都受到必定的影响。虽然经过降级策略和运维配套设施快速的解决了问题,可是也引起了咱们的进一步思考。在架构上咱们会尽可能保证在开发效率、系统架构、部署和运维成本等方面达到必定的平衡,以免过分设计或者架构支撑不了业务。这到了须要作一些事情的时候,咱们把核心业务和非核心业务在七层和应用层作了部署上的隔离。

作完上面的核心业务和非核心业务拆分以后,接口互相之间的依赖影响下降不少。可是尚未解决核心业务或者非核心业务内部接口之间的依赖影响问题。因此接下来也更进一步,针对部分场景也作了内部隔离,经过限定每一个接口最多只能使用的固定处理线程数方式,来避免由于单个集群内某个接口的问题致使整个集群出问题的状况发生。

以上主要是在接口层面作隔离,而在依赖的资源及其外部服务方面,若是没有相应的隔离机制,也会有互相依赖影响的问题,比较典型的有 memcached slab calcification (钙化~)问题等。因此咱们也在 memcached、mysql 等核心资源层面作了拆分。

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Memcached采用LRU(Least Recent Used)淘汰算法,在内存容量满时踢出过时失效和LRU数据,为新数据腾出内存空间。不过该淘汰算法在内存空间不足以分配新的Slab状况下,这时只会在同一类Slab内部踢出数据。即当某个Slab容量满,且不能在内存足够分配新的Slab,只会在相同Slab内部踢出数据,而不会挪用或者踢出其余Slab的数据。这种局部剔除数据的淘汰算法带来一个问题: Slab钙化

Slab钙化下降内存使用率,若是发生Slab钙化,有三种解决方案:

1) 重启Memcached实例,简单粗暴,启动后从新分配Slab class,可是若是是单点可能形成大量请求访问数据库,出现雪崩现象,冲跨数据库。

2) 随机过时:过时淘汰策略也支持淘汰其余slab class的数据,twitter工程师采用随机选择一个Slab,释放该Slab的全部缓存数据,而后从新创建一个合适的Slab。

3) 经过slab_reassign、slab_authmove参数控制。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

『九个月实现破亿用户的可扩展架构』学习笔记 - blankyao 的代码随想 - SegmentFault 思否昨晚把美拍架构负责人洪小军在 Qcon 上的『九个月实现破亿用户的可扩展架构』分享看了一遍(其实那场 QCon 我也在现场,可是当时小军这个会场实在太多人了,并且当时北京还没开空调又热又闷,因此我就挑了个凉快的......

昨晚把美拍架构负责人洪小军在 Qcon 上的『九个月实现破亿用户的可扩展架构』分享看了一遍(其实那场 QCon 我也在现场,可是当时小军这个会场实在太多人了,并且当时北京还没开空调又热又闷,因此我就挑了个凉快的会场去听了哈哈),感受有很多值得学习的地方,在这里记录一下,强烈建议你们把视频从头至尾看一遍,不要只看 ppt。尤为是身在创业公司且公司业务发展速度比较快的同窗。

总的一个中心思想是在不一样阶段选择最适合本身的方案。这句话提及来简单,可是背后的各类辛酸泪以及血的教训只有亲历者才能理解了。下面咱们从各个角度分别来看一下。

对了,忘了说一个前提了,美拍从上线到发展到一亿用户只经历了短短几个月的时间,在这业界应该是没有几个先例的,这也是前面为何说必定要仔细看看。另外说个八卦,听说美图的第一个后端开发(也是惟一的一个)在刚上线时连续三天没回家...

首先先从架构上来讲,看下美拍经历的几个阶段:

  1. 极简化设计(快速发布上线)
  2. 保持简单行设计(产品快速迭代)
  3. 可扩展和高可用保证(用户量到必定量级)
  4. 高可扩展和高可用保证

而后咱们来看下美拍一路走来遇到的问题:

  1. MySQL 慢查询
  2. MySQL 写入瓶颈
  3. redis 超时
  4. memcached 命中率奇低
  5. 服务相互依赖
  6. 监控报警不稳定
  7. CDN 服务各类故障
  8. 添加字段成本高
  9. 量级上来后,MySQL 继续慢

而后,咱们按服务维度把每个服务拆开,看下每个服务在美拍架构上的迭代过程。

1、MySQL

MySQL 是最重要的一个服务,在美拍架构里经历了屡次迭代。在初版直接就是一个实例,为了保持代码的简单,业务逻辑能在数据库里作的都放到数据库作了,好比 Feed 功能,直接用 MySQL 的 join 查询。

可是后来就出现了一些慢查询的状况,这时候作了主从,作读写分离,多个从库用来作查询。再到后来出现写入也慢的状况,这时候也没有作架构上的优化,而是升级硬件,由于如今正是业务高速发展阶段,须要极简化设计,这个阶段更多精力要放在业务开发上(估计当时也木有招到合适的人:))。

过了一段时间又开始出现写入慢的状况,这时候才开始作分表。可是等到了重心放在扩展性和可用性上时,又遇到了新的问题,一个很大的问题仍是写入慢,另一个就是随着数据量的增大,添加字段成本特别的高。针对这两个问题作了下面两个方案:

  1. 异步写入,作到前端永远可写,后面复杂的事情放到队列里面去异步的作
  2. 索引和数据分离,把须要索引的字段单独拆出来一个表,其余数据用 kv 存储,value 就是全部属性和值的 pb 二进制数据,解决家字段困难的问题

这个时候针对 MySQL 的架构优化才告了一段落 :)

2、缓存

缓存主要用到了 memcache 和 redis(redis 应该主要是用在队列和计数服务)。在量比较小的时候就是简单粗暴的用,可是很快就遇到了 redis 超时的问题,这时候对 redis 扩容,使用多 slave 架构。而后是 rdb dump 时影响用户请求的问题,解决方法一是在凌晨访问量低的时候才去 dump,二是用不对外服务的机器来作 dump。

而后 memcached 遇到了命中率很低的问题,一个大问题就是容量瓶颈,这没啥好说的,扩容(小军有提到,要随时作好扩容的准备)。另一个就是 slab calcification 的问题(又叫 slab 钙化问题,这个是 memcached 的内存分配机制致使的,简单来讲就是 memcached 会内存分红 N 个 slab,当新添加一个内存对象时会根据这个对象的大小来选择不一样的 slab,若是没有合适的就会建立一个 slab,那若是这时候剩余内存不足以分配一个 slab 呢?这时候就出现了钙化问题了),美拍当时的解决办法是核心业务隔离部署,避开这个问题。

到可用性保证阶段,缓存的可用性就更加的很是的重要了,缓存挂了可能就整个系统都挂了,很难收场,因此就要保证缓存的可用性。这时候作了主从的优化,master 也承担读查询,以保证缓存热度,slave 穿透到 master,master 穿透到 slave,防止单点故障

3、运维

在初期只是简单的监控告警,有时候出问题了可能收不到告警或者看不到是啥地方出问题,后来逐渐完善监控告警,且监控告警是用配置比较高的服务器,保证监控告警的可用性。而后假如更多监控维度和更多日志,方便定位问题。对依赖的第三方服务和资源作开关,出问题时能够经过服务的开关保证核心路径可用。

4、第三方服务

主要提到的是 CDN 服务。其中一个很大的问题就是 DNS 被攻击、被劫持,除了和运营商保持沟通外,还作了多服务商配合的策略,好比一样的数据在多个云服务那里作冗余,客户端在访问时若是出现问题就切换到其余的访问地址,而且在客户端作了服务端可用性探测。这也是个很是有价值的经验。

5、技术栈

整个看下来会发现美拍的架构作的很是的稳,小军也有提到,在项目初期高速发展阶段作架构时要克服对完美架构的欲望、克服对新技术的欲望,先让系统跑起来

可是在整个迭代过程当中,美拍也一直在引入新技术,好比在团队不太熟悉时先在部分业务上使用 MongoDB,在注重可扩展和可用性阶段,引入 java 作业务逻辑,引入 c 作底层基础服务。

经过这个分享能够学习到一个系统从 0 到亿的架构迭代过程,可是更多的仍是在于实践,估计美拍走过的坑也远不止小军分享里提到的这些,每个点均可能出现 N 多的问题,每一个点均可以展开不少话题来说。但愿能看到更多相似的有价值的分享!

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

综合来看,分级隔离本质上也是在解决服务之间依赖影响问题。

资源冗余

由于短视频是一个比较耗带宽的服务,所以在通用的应用自身资源冗余的状况下,还须要考虑到服务所依赖的外部资源,好比 CDN 和云存储服务自己的状况。对于 CDN 层面,可能还要考虑不一样厂商在不一样区域不一样运营商下的资源冗余状况。而依赖的云服务等,这些服务自己从对外角度看是一个可无限扩展的服务,理论上经过扩展就可以知足性能需求,可是在使用每每会受限于实现,由于内部不必定是一个彻底隔离的场景,好比说和别的企业服务混跑,同时可能只会分配对应的资源池,但这个资源超过性能预期的时候,不是一个可自动动态伸缩调度的场景。

容灾

美拍的容灾主要分为自身服务容灾、CDN 容灾、云存储容灾等。

自身服务容灾主要包含一些典型的容灾场景,好比 cache 容灾,经过多级 cache、cache 的分片 hash 的方式、以及本地 cache 的方式来解决。目前咱们这边的容灾也借鉴了微博的多级 cache 机制的机制,针对核心的 cache 资源会有主备节点,避免单一节点挂掉后,穿透会压垮后端 DB,同时对于请求量特别大的场景,好比对于某个热点资源访问量很大的状况下,也会在以前增长一层 L1 的 LRU cache 来规避和缓解这一问题。

 


 

CDN 容灾主要经过接入多家供应商进行互备,而后经过一些基调检测不一样服务厂商的链路和服务状态,当发现服务有问题的时候,经过 DNS 进行区域的切换。不过不一样 CDN 厂商的服务表现不对等,因此在选型 CDN 厂商的话,须要侧重关注可用性、节点布点和链路情况、回源量、资源冗余量、晚高峰的链路情况、以及对于多媒体是否有单独优化等等来评估靠谱性

云存储容灾,目前美拍也主要使用两家互备的方式,由于国内的网络链路情况容易发生问题容易致使个别上传服务失败,以及云服务厂商服务挂掉的状况咱们须要保证咱们的服务可用。目前的作法是上传优先走主的云服务,若是上传失败的话,那么就会启用备的云服务。而后服务端层面也能够控制总体降级的方式,能够直接从主云服务直接降级读写备云服务。 基于天天的统计来看,经过这个方式至少提高上传的 0.1% 以上的可用性,在某些极端状况下,可能达到 1% 的可用性,固然这一块经过网络链路优化可能使得可用性状况没有数据中那么差。不过他的主要做用是在当某个云服务厂商节点服务出现短暂不可用或者长时间不可用的时候,咱们也不会受太大影响。

 


 

5、后续的一些发展

随着短视频的不断的发展,以及实时直播的崛起,带宽的压力会愈来愈大,因此可以结合着 P2P + CDN 的方式来缓解服务端的带宽压力,不过 P2P 主要会面临着防火墙的问题、以及节点网络质量的影响,同时也依赖与视频播放的热度,这种对于效果都会有一些影响,同时为了更好的播放流畅度,单一的 P2P 没法知足需求,须要基于 P2P 和 CDN 的辅助进行。

带宽的另一个节省之道,就是经过更好的编码标准来进行优化,好比 H.265 的编码标准,经过这个可以节省一半的流量。不过目前 H.265 在硬编支持不是很好,只有个别手机机型支持,而软编码的方式相比与 H.264,编解码速度要慢个几倍,这种对于能耗消耗比较高,处理也比较慢。而在往 H.265 演化的过程当中,解码的普及程度也将会比编码来得更早。由于在解码算法层面,现有开源的方案还有很大的优化空间,以现有的手机硬件配置,是存在能够经过算法优化达到能够支撑 H.265 的空间。因此随着解码算法的不断优化和硬件的不断升级,解码普及的时间点也应该会比你们预期的时间来得更早,晋时也将会有更大比例的端能支持 H.265 的解码,对于 H.265 的普及奠基了很好的基础。

H.265 的普及理想状况是须要很大比例的端上设备在编码和解码层面都有支持,在解码更早普及的状况下,那么实际上是有一种中间过渡方式:上传端上传 H.264 数据,服务端转为 H.265,播放端根据自身机器情况选择使用 H.264 或者 H.265 数据。这样的方案须要服务端须要额外作一次转码,而且存储成本也会提高。在有更大比例的端上支持 H.265 后,这样虽然有额外的成本开销,可是相比使用 H.265 带来的带宽成本的节省可能就愈来愈能够忽略掉。而且也能够根据访问热度状况作控制,取得二者更好的平衡。

另一个方向,目前美拍会越多越多的把一些客户端的图片视频美化算法云端化,以服务的形式暴露给内部其余服务使用,以便可以支撑更多围绕 “美” 体系建设的产品生态链。这主要会面临的架构难点,就是资源消耗高。而这个的解决会依赖与两种方式,一种经过硬件 GPU、协处理器、CPU SIMD 指令等来优化性能,同时还须要解决架构的视频处理集群的自动弹性调度的问题,同时对于一些场景,好比相似与 H5 的推广页面,会逐步经过结合公有云调度的方式来解决。

本文转载来自高可用架构 「ArchNotes」公众号

 
   


刘道儒/1.7 微博“异地多活”部署经验谈69
1.7.1 微博异地多活建设历程69
1.7.2 微博异地多活面临的挑战70
1.7.3 异地多活的最佳实践.73
1.7.4 异地多活的新方向74

微博 “异地多活” 部署经验谈 - InfoQ

【编者按】近日,InfoQ 专访了阿里巴巴的研究员林昊(花名毕玄),了解了他们的数据中心异地多活项目的前因后果。本文在微博上引发了不少讨论。新浪微博的高级技术经理刘道儒( @liudaoru )也总结了微博平台的一些经验。

正文

异地多活的好处阿里巴巴的同窗已经充分阐述,微博的初始出发点包括异地灾备、提高南方电信用户访问速度、提高海外用户访问速度、下降部署成本(北京机房机架费太贵了)等。经过实践,咱们发现优点还包括异地容灾、动态加速、流量均衡、在线压测等,而挑战包括增长研发复杂度、增长存储成本等。

微博外部历程

先说说微博外部的历程,整个过程可谓是一波多折。微博的主要机房都集中在北京,只有很小一部分业务在广州部署,2010 年 10 月,因微博高速发展,因此准备扩大广州机房服务器规模,并对微博作异地双活部署。

初版跨机房消息同步方案采起的是基于自研的 MytriggerQ(借助 MySQL 从库的触发器将 INSERT、UPDATE、DELETE 等事件转为消息)的方案,这个方案的好处是,跨机房的消息同步是经过 MySQL 的主从完成的,方案成熟度高。而缺点则是,微博同一个业务会有好几张表,而每张表的信息又不全,这样每发一条微博会有多条消息前后到达,这样致使有较多时序问题,缓存容易花。(得join)

第一套方案未能成功,但也让咱们认识到跨机房消息同步的核心问题,并促使咱们全面下线 MytriggerQ 的消息同步方案,而改用基于业务写消息到 MCQ( MemcacheQ ,新浪自研的一套消息队列,类 MC 协议)的解决方案。

基于业务写消息到消息队列

 

 

 

2011 年末在微博平台化完成后,开始启用基于 MCQ 的跨机房消息同步方案,并开发出跨机房消息同步组件 WMB(Weibo Message Broker)。通过与微博 PC 端等部门同窗的共同努力,终于在 2012 年 5 月完成 Weibo.com 在广州机房的上线,实现了 “异地双活”。

因为广州机房整体的机器规模较小,为了提高微博核心系统容灾能力,2013 年年中咱们又将北京的机房进行拆分,至此微博平台实现了异地三节点的部署模式。依托于此模式,微博具有了在线容量评估、分级上线、快速流量均衡等能力,应对极端峰值能力和应对故障能力大大提高,以后历次元旦、春晚峰值均顺利应对,平常上线致使的故障也大大减小。上线后,根据微博运营状况及成本的须要,也曾数次调整各个机房的服务器规模,可是整套技术上已经基本成熟。

异地多活面临的挑战

根据微博的实践,通常作异地多活都会遇到以下的问题:

  • 机房之间的延时:微博北京的两个核心机房间延时在 1ms 左右,但北京机房到广州机房则有近 40ms 的延时。对比一下,微博核心 Feed 接口的总平均耗时也就在 120ms 左右。微博 Feed 会依赖几十个服务上百个资源,若是都跨机房请求,性能将会惨不忍睹;
  • 专线问题:为了作广州机房外部,微博租了两条北京到广州的专线,成本巨大。同时单条专线的稳定性也很难保障,基本上每月都会有或大或小的问题;
  • 数据同步问题:MySQL 如何作数据同步?HBase 如何作数据同步?还有各类自研的组件,这些通通要作多机房数据同步。几十毫秒的延时,加上路途遥远致使的较弱网络质量(咱们的专线每月都会有或大或小的问题),数据同步是很是大的挑战;
  • 依赖服务部署问题:如同阿里巴巴目前只作了交易单元的 “异地双活”,微博部署时也面临核心服务过多依赖小服务的问题。将小服务所有部署,改形成本、维护成本过大,不部署则会遇到以前提到的机房之间延时致使总体性能没法接受的问题;
  • 配套体系问题:只是服务部署没有流量引入就不能称为 “双活”,而要引入流量就要求配套的服务和流程都能支持异地部署,包括预览、发布、测试、监控、降级等都要进行相应改造。

微博异地多活解决方案

因为几十毫秒的延时,跨机房服务调用性能不好,异地多活部署的主体服务必需要作数据的冗余存储,并辅以缓存等构成一套独立而相对完整的服务。数据同步有不少层面,包括消息层面、缓存层面、数据库层面,每个层面均可以作数据同步。因为基于 MytriggerQ 的方案的失败,微博后来采起的是基于 MCQ 的 WMB 消息同步方案,并经过消息对缓存更新,加上微博缓存高可用架构,能够作到即使数据库同步有问题,从用户体验看服务仍是正常的。

这套方案中,每一个机房的缓存是彻底独立的,由每一个机房的 Processor(专门负责消息处理的程序,类 Storm)根据收到的消息进行缓存更新。因为消息不会重复分发,并且信息完备,因此 MytriggerQ 方案存在的缓存更新脏数据问题就解决了。而当缓存不存在时,会穿透到 MySQL 从库,而后进行回种。可能出现的问题是,缓存穿透,可是 MySQL 从库若是此时出现延迟,这样就会把脏数据种到缓存中。咱们的解决方案是作一个延时 10 分钟的消息队列,而后由一个处理程序来根据这个消息作数据的从新载入。通常从库延时时间不超过 10 分钟,而 10 分钟内的脏数据在微博的业务场景下也是能够接受的。

微博的异地多活方案以下图(三个节点相似,消息同步都是经过 WMB):

 

 

跟阿里巴巴遇到的问题相似,咱们也遇到了数据库同步的问题。因为微博对数据库不是强依赖,加上数据库双写的维护成本过大,咱们选择的方案是数据库经过主从同步的方式进行。这套方案可能的缺点是若是主从同步慢,而且缓存穿透,这时可能会出现脏数据。这种同步方式已运行了三年,总体上很是稳定,没有发生由于数据同步而致使的服务故障。从 2013 年开始,微博启用 HBase 作在线业务的存储解决方案,因为 HBase 自己不支持多机房部署,加上早期 HBase 的业务比较小,且有单独接口能够回调北京机房,因此没有作异地部署。到今年因为 HBase 支撑的对象库服务已经成为微博很是核心的基础服务,咱们也在规划 HBase 的异地部署方案,主要的思路跟 MySQL 的方案相似,同步也在考虑基于 MCQ 同步的双机房 HBase 独立部署方案。

阿里巴巴选择了单元化的解决方案,这套方案的优点是将用户分区,而后全部这个用户相关的数据都在一个单元里。经过这套方案,能够较好的控制成本。但缺点是除了主维度(阿里巴巴是买家维度),其余全部的数据仍是要作跨机房同步,总体的复杂度基本没下降。另外就是数据分离后因为拆成了至少两份数据,数据查询、扩展、问题处理等成本均会增长较多。总的来说,我的认为这套方案更适用于 WhatsApp、Instagram 等国外业务相对简单的应用,而不适用于国内功能繁杂、依赖众多的应用

数据同步问题解决以后,紧接着就要解决依赖服务部署的问题。因为微博平台对外提供的都是 Restful 风格的 API 接口,因此独立业务的接口能够直接经过专线引流回北京机房。可是对于微博 Feed 接口的依赖服务,直接引流回北京机房会将平均处理时间从百毫秒的量级直接升至几秒的量级,这对服务是没法接受的。因此,在 2012 年咱们对微博 Feed 依赖的主要服务也作了异地多活部署,总体的处理时间终于降了下来。固然这不是最优的解决方案,但在当时微博业务体系还相对简单的状况下,很好地解决了问题,确保了 2012 年 5 月的广州机房部署任务的达成。

而配套体系的问题,技术上不是很复杂,可是操做时却很容易出问题。好比,微博刚开始作异地多活部署时,测试同窗没有在上线时对广州机房作预览测试,曾经致使过一些线上问题。配套体系须要覆盖整个业务研发周期,包括方案设计阶段的是否要作多机房部署、部署阶段的数据同步、发布预览、发布工具支持、监控覆盖支持、降级工具支持、流量迁移工具支持等方方面面,并需开发、测试、运维都参与进来,将关键点归入到流程当中。

关于为应对故障而进行数据冗余的问题,阿里巴巴的同窗也作了充分的阐述,在此也补充一下咱们的一些经验。微博核心池容量冗余分两个层面来作,前端 Web 层冗余同用户规模成正比,并预留平常峰值 50% 左右的冗余度,然后端缓存等资源因为相对成本较低,每一个机房均按照总体两倍的规模进行冗余。这样若是某一个机房不可用,首先咱们后端的资源是足够的。接着咱们首先会只将核心接口进行迁移,这个操做分钟级便可完成,同时因为冗余是按照总体的 50%,因此即便全部的核心接口流量所有迁移过来也能支撑住。接下来,咱们会把其余服务池的前端机也改成部署核心池前端机,这样在一小时内便可实现总体流量的承接。同时,若是故障机房是负责数据落地的机房,DBA 会将从库升为主库,运维调整队列机开关配置,承接数据落地功能。而在整个过程当中,因为咱们核心缓存能够脱离数据库支撑一个小时左右,因此服务总体会保持平稳。

异地多活最好的姿式

以上介绍了一下微博在异地多活方面的实践和心得,也对比了一下阿里巴巴的解决方案。就像没有完美的通用架构同样,异地多活的最佳方案也要因业务情形而定。若是业务请求量比较小,则根本没有必要作异地多活,数据库冷备足够了。无论哪一种方案,异地多活的资源成本、开发成本相比与单机房部署模式,都会大大增长。

如下是方案选型时须要考虑的一些维度:

  • 可否整业务迁移:若是机器资源不足,建议优先将一些体系独立的服务总体迁移,这样能够为核心服务节省出大量的机架资源。若是这样以后,机架资源仍然不足,再作异地多活部署。
  • 服务关联是否复杂:若是服务关联比较简单,则单元化、基于跨机房消息同步的解决方案均可以采用。无论哪一种方式,关联的服务也都要作异地多活部署,以确保各个机房对关联业务的请求都落在本机房内。
  • 是否方便对用户分区:好比不少游戏类、邮箱类服务,因为用户能够很方便地分区,就很是适合单元化,而 SNS 类的产品由于关系公用等问题不太适合单元化
  • 谨慎挑选第二机房:尽可能挑选离主机房较近(网络延时在 10ms 之内)且专线质量好的机房作第二中心。这样大多数的小服务依赖问题均可以简化掉,能够集中精力处理核心业务的异地多活问题。同时,专线的成本占比也比较小。以北京为例,作异地多活建议选择天津、内蒙古、山西等地的机房
  • 控制部署规模:在数据层自身支持跨机房服务以前,不建议部署超过两个的机房。由于异地两个机房,异地容灾的目的已经达成,且服务器规模足够大,各类配套的设施也会比较健全,运维成本也相对可控。当扩展到三个点以后,新机房基础设施磨合、运维决策的成本等都会大幅增长。
  • 消息同步服务化:建议扩展各自的消息服务,从中间件或者服务层面直接支持跨机房消息同步,将消息体大小控制在 10k 如下,跨机房消息同步的性能和成本都比较可控。机房间的数据一致性只经过消息同步服务解决,机房内部解决缓存等与消息的一致性问题。跨机房消息同步的核心点在于消息不能丢,微博因为使用的是 MCQ,经过本地写远程读的方式,能够很方便的实现高效稳定的跨机房消息同步。

异地多活的新方向

时间到了 2015 年,新技术层出不穷,以前不少成本很高的事情目前都有了很好的解决方案。接下来咱们将在近五年异地多活部署探索的基础上,继续将微博的异地多活部署体系化。

升级跨机房消息同步组件为跨机房消息同步服务。面向业务隔离跨机房消息同步的复杂性,业务只须要对消息进行处理便可,消息的跨机房分发、一致性等由跨机房同步服务保障。且能够做为全部业务跨机房消息同步的专用通道,各个业务都可以复用,相似于快递公司的角色。

推动 Web 层的异地部署。因为远距离专线成本巨大且稳定性很难保障,咱们已暂时放弃远程异地部署,而改成业务逻辑近距离隔离部署,将 Web 层进行远程异地部署。同时,计划再也不依赖昂贵且不稳定的专线,而借助于经过算法寻找较优路径的方法经过公网进行数据传输。这样咱们就能够将 Web 层部署到离用户更近的机房,提高用户的访问性能。依据咱们去年作微博 Feed 全链路的经验,中间链路占掉了 90% 以上的用户访问时间将 Web 层部署的离用户更近,将能大大提高用户访问性能和体验

借助微服务解决中小服务依赖问题。将对资源等的操做包装为微服务,并将中小业务迁移到微服务架构。这样只须要对几个微服务进行异地多活部署改造,众多的中小业务就再也不须要关心异地部署问题,从而能够低成本完成众多中小服务的异地多活部署改造。

利用 Docker 提高前端快速扩容能力。借助 Docker 的动态扩容能力,当流量过大时分钟级从其余服务池摘下一批机器,并完成本服务池的扩容。以后能够将各类资源也归入到 Docker 动态部署的范围,进一步扩大动态调度的机器源范围。

以上是对微博异地多活部署的一些总结和思考,但愿可以对你们有所启发,也但愿看到更多的同窗分享一下各自公司的异地多活架构方案。

编后语

为了更好地向读者输出更优质的内容,InfoQ 将精选来自国内外的优秀文章,通过整理审校后,发布到网站。本文首发于 “微博平台架构” 微信公众号,已由原做者受权 InfoQ 中文站转载。

关于做者

刘道儒,毕业于北京信息工程学院,现任微博平台研发高级技术经理、Feed 项目技术负责人,负责 Feed 体系后端研发,前后在 TRS、搜狗、新浪微博从事社区 & 社交业务研发,专一于大规模分布式系统的研发、高可用等领域。他曾表明平台在 2012 年主导了微博广州机房部署项目以及北京双机房部署项目。

 


孙宇聪/1.8 来自Google 的高可用架构理念与实践75
1.8.1 决定可用性的两大因素76
1.8.2 高可用性方案77
1.8.3 可用性7 级图表80
1.8.4 疑问与解惑.81

讲的人话。。。  
来自 Google 的高可用架构理念与实践 - CODING 博客孙宇聪,CTO @ coding.net 。2007 - 2015 年初在 Google 的 Moutain View 担任 SRE 职位。 参与了 Google 的两个项目:第一个是 Youtube

孙宇聪,CTO @ coding.net 。2007 - 2015 年初在 Google 的 Moutain View 担任 SRE 职位。 参与了 Google 的两个项目:第一个是 Youtube,工做内容涵盖 Video transfer、Coding、Streaming、Global CDN 等;第二个是 Google Cloud Platform Team,主要工做是管理 Google 全球 100 万台左右的服务器,开发用于管理 Google 整个云平台的任务调度、协做的集群管理系统 Omega 。

 

 

在 Google 我参与了两个比较大的 Project。

第一个是 YouTube,其中包括 Video transcoding,streaming 等。Google 的量很大,每月会有 1PB 级别的存储量。存储、转码后,咱们还作 Global CDN。到 2012 年的时候,峰值流量达到 10 TBps,全球 10 万个节点,几乎每台机器都是 16/24 核跑满, 10G uplink 也是跑满的状态。

而后我加入了 Google Cloud Platform Team, 也就是 Borg 团队。这个团队的主要工做是就是管理 Google 全球全部的服务器,全球大概有 100 万台左右。另外就是维护 Borg 系统,同时我也是 Omega 系统运维的主要负责人,很惋惜这个项目最后因为各类各样的缘由在内部取消了。

下面我想跟你们分享的是关于可用性、可靠性上面的一些理念和思考。

1、决定可用性的两大因素

谈可用性不须要绕来绕去,你们只谈 SLA 便可。你们能够看下面这个图:

 

 

要谈可用性,首先必须认可全部东西都有不可用的时候,只是不可用程度而已。通常来讲,咱们的观念里一个服务至少要作到 99.9% 才称为基本上可用,是合格性产品。不然基本很难被别人使用。

从 3 个 9 迈向 4 个 9,从 8 小时一下缩短到 52.6 分钟的不可用时间,是一个很大的进步。Google 内部只有 4 个 9 以上的服务才会配备 SRE,SRE 是必须在接到报警 5 分钟以内上线处理问题的,不然报警系统自动升级到下一个 SRE。若是尚未,直接给老板发报警。

你们以前可能据说谷歌搜索服务可用度大概是全球 5 个 9,6 个 9 之间。其实这是一个多层,多级,全球化的概念,具体到每一个节点其实没那么高。好比说当年北京王府井楼上的搜索集群节点就是按 3 个 9 设计的。

有关 SLA 还有一个秘密,就是通常你们都在谈年 SLA,可是年 SLA 除了客户赔款之外,通常没有任何实际工程指导意义。 Google 内部更看重的是季度 SLA,甚至月 SLA,甚至周 SLA。这所带来的挑战就更大了。

为何说看这个图有用,由于 99%、99.9% 是基本能够靠运气搞定的哦。到 3 个 9 能够靠堆人,也就是 3 班倒之类的强制值班基本搞定。可是从 3 个 9 往上,就基本超出了人力的范畴,考验的是业务的自愈能力,架构的容灾、容错设计,灾备系统的完善等等。

说了这么多,做为一个架构者,咱们如何来系统的分解 “提高 SLA” 这一个难题呢。

这里我引入两个工业级别的概念 MTBF 和 MTTR。

MTBF: Mean time between Failures。 用通俗的话讲,就是一个东西有多不可靠,多长时间坏一次。
MTTR: Mean time to recover。意思就是一旦坏了,恢复服务的时间须要多长。

有了这两个概念, 咱们就能够提出:

 

 

一个服务的可用度,取决于 MTBF 和 MTTR 这两个因子。从这个公式出发,结合实际状况,就很好理清高可用架构的基本路数了。那就是: 要么提升 MTBF, 要么下降 MTTR。除此以外别无他法。

要注意的是,考虑 MTBF 和 MTTR 的时候都不能脱离现实。

理论上来讲,做为一个正常人类,收到突发报警、能正确的分析出问题所在、找到正确的解决方案、而且 【正确实施】的时间极限大概是 【两分钟】。这个标准我我的以为是高到天上去了。做为一个苦练多年的 Oncall 工程师,我 2 分钟能看清报警,上了 VPN,找到 dashboard,就不错了。就算是已知问题,有应对方案,能敲对命令,彻底成功,也至少须要 15 - 20 分钟。因此若是按照这个标准的话,管理的服务若是想达到 4 个 9,那么一年只能坏 1 次,2 次就超标了。实现高可用基本靠运气~

回过来接着说说 MTBF 吧。请各位想一下,影响服务 MTBF 的三大因素!

  1. 发布
  2. 发布
  3. 仍是发布!

这个术语上叫 Age Mortality Risk。

通常一个服务只要你不去碰他一年都不会坏一次。更新越频繁,坏的可能性就越大。凡是 Software 都有 BUG,修 BUG 的更新也会引入新的 BUG。发布新版本,新功能是 MTBF 最大的敌人。

2、高可用性方案

说了 MTBF 和 MTTR 这两个定义,那么具体究竟应该如何落地实践来提升可用性呢?

首先说几个你们可能都听腻了的方案

1、提升冗余度,多实例运行,用资源换可用性。

虽然道理很简单,实现起来可不简单,有不少不少细节上的东西须要考虑。

第一个细节:N + 2 应该是标配。

N + 2 就是说平时若是一个服务须要 1 个实例正常提供服务,那么咱们就在生产环境上应该部署 1 + 2 = 3 个节点。你们可能以为 N + 1 很合理,也就是有个热备份系统,比较可以接受。可是你要想到:服务 N + 1 部署只能提供热备容灾,发布的时候就失去保护了。

由于刚才说了, 发布不成功的概率很高!

从另外一个角度来说,服务 N + 2 说的是在丢失两个最大的实例的同时,依然能够维持业务的正常运转。

这其实就是最近常说的两地三中心的概念有点像。

第二个细节: 实例之间必须对等、独立。

千万不要搞一大一小,或者相互依赖。不然你的 N + 2 就不是真的 N + 2。若是两地三中心的一个中心是须要 24 小时才能迁移过去的,那他就不是一个高可用性部署,仍是叫异地灾备系统吧。

第三个细节:流量控制能力很是重要。

想作到高可用,必须拥有一套很是可靠的流量控制系统。这套系统按常见的维度,好比说源 IP,目标 IP 来调度是不够的,最好能按业务维度来调度流量。好比说按 API, 甚至按用户类型,用户来源等等来调度。

为何?由于一个高可用系统必需要支持一下几种场景:

  1. Isolation。A 用户发来的请求可能和 B 用户发来的请求同时处理的时候有冲突,须要隔离。
  2. Quarantine。用户 A 发来的请求可能资源消耗超标,必须能将这类请求钉死在有限的几个节点上,从而顾全大局。
  3. Query-of-death。你们都遇到过吧。上线以后一个用户发来个一个异常请求直接搞挂服务。连续多发几个,整个集群都挂没了,高可用还怎么作到?那么,对这种类型的防范就是要在死掉几台服务器以后能够自动屏蔽相似的请求。须要结合业务去具体分析。

可是想要达到高可用,这些都是必备的,也是必定会遇到的场景。仍是那句话,靠人是没戏的。

2、变动管理(Change Management)

还记得影响 MTBF 最大的因子吗?发布质量不提升,一切都是空谈。

第一点: 线下测试(Offline Test)

线下测试永远比线上调试容易一百倍,也安全一百倍。

这个道理很简单,就看执行。若是各位的团队尚未完整的线下测试环境,那么个人意见是不要再接新业务了,花点时间先把这个搞定。这其中包括代码测试、数据兼容性测试、压力测试等等。

台上一分钟,台下十年功。

可用性的阶段性提升,不是靠运维团队,而是靠产品团队。能在线下完成的测试,毫不拍脑门到线上去实验。

第二点:灰度发布

这个道理提及来好像也很普通,可是具体实施起来是颇有讲究的。

首先灰度发布是速度与安全性做为妥协。他是发布众多保险的最后一道,而不是惟一的一道。若是只是为了灰度而灰度,故意人为的拖慢进度,反而形成线上多版本长期间共存,有可能会引入新的问题。

作灰度发布,若是是匀速的,说明没有理解灰度发布的意义。通常来讲阶段选择上从 1% -> 10% -> 100% 的指数型增加。这个阶段,是根据具体业务不一样按维度去细分的。

这里面的重点在于 1% 并不全是随机选择的,而是根据业务特色、数据特色选择的一批有极强的表明性的实例,去作灰度发布的小白鼠。甚至于每次发布的 第一阶段用户(咱们叫 Canary / 金丝雀) ,根据每次发布的特色不一样,是人为挑选的。

若是要发布一个只给亚洲用户使用的功能,很明显用美国或欧洲的集群来作发布实验,是没有什么意义的。从这个角度来想,是否是灰度发布可作的事情不少不少?真的不仅是按机器划分这么简单。

回到本质:灰度发布是上线的最后一道安全防御机制。即不能过慢,让产品团队过分依赖,也不能过于随机,失去了他的意义。

总之,灰度发布,全在细节里。

第三点:服务必须对回滚提供支持

这点不容许商量!

这么重要的话题,我还要用一个感叹号来强调一下!

可是估计现实状况里,你们都听过各类各样的理由吧。我这里有三条买也买不到的秘籍,今天跟你们分享一下,保证药到病除。

理由 1:我这个数据改动以后格式跟之前的不兼容了,回退也不能正常!
秘籍 1:设计、开发时候就考虑好兼容性问题!!!好比说数据库改字段的事就不要作,改为另加一个字段就好。数据存储格式就最好采用 protobuf 这种支持数据版本、支持先后兼容性的方案。最差的状况,也要在变动实施『以前』,想清楚数据兼容性的问题。没有回滚脚本,不给更新,起码作到有备而战。

理由 2:我这个变动删掉东西了!回退以后数据也没了!
秘籍 2:你必定是在逗我。把这个变动打回去,分红两半。第一半禁止访问这个数据。等到发布以后真没问题了,再来发布第二半,第二半真正删掉数据。这样第一半实施以后须要回滚还能够再回去

理由 3:我这个变动发布了以后, 其余依赖这个系统的人都拿到了错误的数据,再回退也没用了,他们不会再接受老数据了!
秘籍 3:这种比较常见出如今配置管理、缓存等系统中。对这类问题,最重要的就是, 应该开发一种跟版本无关的刷新机制。触发刷新的机制应该独立于发布过程要有一个强制刷新数据的手段

以上三个秘籍覆盖了 100% 的回滚兼容性问题,若是有不存在的,请务必告诉我!

回滚兼容性问题,是一个总体难题。只有开发和运维都意识到这个问题的严重性,才能从总体上解决这个问题。而解决不了回滚难题,就不可能达到高可用

3、可用性 7 级图表

说完了变动管理,给你们带来一个 7 级图表,能够看看本身的服务到底在哪一个可用性的级别上。

当一个服务挂了的时候......

第一级:Crash with data corruption, destruction.

内存数据库就容易这样。出现个意外状况,全部数据全丢。写硬盘写到一半,挂了以后,不光进程内数据没了,老数据都丢光了。碰上这样的系统,我只能对你表示同情了。

第二级:Crash with new data loss.

通常来讲 正常的服务都应该作到这一点...... 。挂了以后最多只丢个几秒以内的数据。

第三级:Crash without data loss.

要达到这一级,须要付出必定程度的技术投入。起码搞清楚如何绕过 OS 各类 Cache,如何绕过硬件的各类坑

第四级:No crash, but with no or very limited service, low service quality.

作的好一点的系统,不要动不动就崩溃了...... 若是一个程序可以正常处理异常输入,异常数据等,那么就给刚才说的高级流控系统创造了条件。能够把其余的用户流量导入过来,把问题流量发到一边去,不会形成太大的容量损失。

第五级:Partial or limited service, with good to medium service quality.

这一级就还好了,若是多个业务跑在同一个实例上,那么起码不要所有坏掉。有部分服务,比彻底没有服务要好

第六级:Failover with significant user visible delay, near full quality of service

上升到这一级别,才摸到高可用的门,也就是有容灾措施。可是可能自动化程度不高,或者是一些关键性问题没有解决,因此业务能恢复,就是比较慢。

第七级:Failover with minimal to none user visible delay, near full quality

of service.

这边蝴蝶扇了一下翅膀,天空落了个打雷,打掉了一整个机房,结果业务彻底没受影响。蓝翔技校一铲子下去,互联网都要抖一抖。嘿嘿, 高可用就是为了这种事情作准备。

Q & A

1. 有什么评测系统吗?

评测系统的第一步是收集足够的信息。想知道本身的服务是否是高可用,必须得先监测啊!不光黑盒监测,还要有白盒监测。若是有一个自动化的 SLA 监控系统,能显示实时的 SLA 变化 ,会对系统的开发计划有很强烈的指导做用。

2. 能详细说一下作到 “crash without data loss” 须要在哪些点上下功夫吗?

这个事情提及来简单,实际实现起来很是复杂。 由于不少东西深究起来都有无数的坑。 好比说:

OS 的 Cache 如何绕过。
系统硬件可能也有内置的 Cache,Firmware 也可能有 BUG 等等等等。还有一些集群系统为了所谓的性能实现的 fake sync。

这里是列不全的。我提出这个等级的意思,是想让你们有这个意识去系统化的应对这个问题。好比说关键数据是否是要多存几分,而后作一些 destruction 测试。好比多模拟断电等等的极端状况,这样才能有备无患。扫雷比触雷要容易多了。

3. 如今 Coding.net 到几个 9 了,7 张图中第几级了,改造花了多长时间,有哪些坑分享下?

首先高可用是按业务来的,不是全部业务都能作到高可用,也不是全部都须要作到高可用。咱们下了很大精力在关键业务上,好比说 Git 系统的流控,数据安全等等,其余的就没办法啦。

4. 开发团队要怎样配合?周期怎么样配合?侧重点各自在哪 (开发更侧重业务)?

首先就是要肯定一个共同目标。高可用是有代价的,你的业务须要作到什么程度,必定是一个系统性的考虑。给你们举一个例子,Youtube 这么多视频, 可是每一个视频的每种格式,只存了 1 份。因此可用性确定受影响了。可是,数据量实在是太大了,而后各类小猫视频实在是不重要。相比之下,广告视频常常存 8 份。因此!想要提升可用性,必需要和开发团队找到一个共同目标。这里再给你们一个秘籍,那就是 error budget。跟开发团队肯定一个可用度,好比说 99% 。 若是业务团队搞出来的东西很烂,各类情况,最后达不到这个标准。那么对不起,暂时别发新功能,只修 BUG。

5. 谷歌的 SRE 工程师用了哪些开源工具来管理百万机器?

比较惭愧,咱们没用什么开源工具,都是内部本身开发的。企业内部管理用了 Puppet,可是生产系统上没有。

6. 请问一下实现独立对等的 N+2 服务使用什么架构比较好,LVS+Keepalive 的双机热备是否合适?

莫非如今不都用 haproxy / nginx 之类的 7 层代理?可是其实这个原理都差很少。只要达到你的目的,能够动态切换就好。

https://www.jianshu.com/p/fa937b8e6712

四层、七层负载均衡的区别

 

7. “能够把其余的用户流量导入过来。把问题流量发到一边去,不会形成太大的容量损失。” 这句话怎么理解呢? 另外如何区分问题流量?

这句话说的是刚才提到的高可用必不可少的流控系统。任何一个系统都不是完美的,总会有各类各样的 hot spot,weak spot。问题流量的定义是跟业务紧密相关的。我再举一个例子:当年 Youtube 的 CDN 服务器有个问题,后端存储慢了以后,前端的请求会聚在一块儿,就像水管同样,因而内存就爆了。忽然压力太高,确定就挂了。如何处理这个问题? 最后流控系统升级,每一个实例本身汇报本身的内存情况,超标以后流控系统自动绕过他。把这个问题变成了自动化处理的方案,问题面大大缩小了。再举一个例子,搜索系统是典型的热点密集型系统。有的冷僻词, 查一次要去各类读硬盘。而热词,消耗很小。因此流控系统作了个功能每一个请求回复都带了 cost 值,流控系统自动均衡了整个集群。——> 就应该强化学习搞

8. 关于回滚那里,若是我要新增一个删除功能,怎么作到把这个操做拆成两半,用户作了删除操做,但是禁止删除数据,那是否会产生数据不一致的?

这个是刚才说的那个秘籍第二条。其实秘籍第二条就是拆!没有什么发布是不能拆的。 拆到能够安全的往前滚再日后滚

9. 100W 台服务器如何自动化管理、及时发现故障、自动修复、作出报警,可否简单介绍介绍?

这个问题其实没那么复杂。就是在每一个机器上运行一个 agent,这个 agent 按期进行检查操做,有问题就通知管理系统自动下线。只要注意平时收集问题现象就好了。好比说线上忽然出现了一个时间不一样的问题,那么就把他加到这个 agent 里去,下次这个问题就是自动检测自动修复的了。

10. 有没有什么好办法处理 query to death?

这个问题比较难,通常是要作一层智能一点的业务 proxy 。业务 proxy 检测到请求发到哪,哪一个后端挂,就能够进行一些处理了。还有一个办法是在挂以前后端记 log,处理以前记上。我要处理这个请求了,而后处理一半挂掉了。重启以后,检查 log 发现上次是处理这个请求挂了,那么就能够屏蔽掉这个请求。

转载自 "高可用架构 (ArchNotes)" 微信公众号

 


那 谁/1.9 深刻理解同步/异步与阻塞/非阻塞区别84
1.9.1 同步与异步.84
1.9.2 阻塞与非阻塞85
1.9.3 与多路复用I/O 的联系86



第2 章 高可用架构原理与分布式实践.88
黄东旭/2.1 Codis 做者细说分布式Redis 架构设计88
2.1.1 Redis、Redis Cluster 和Codis88
2.1.2 咱们更爱一致性90
2.1.3 Codis 在生产环境中的使用经验和坑91
2.1.4 分布式数据库和分布式架构.94
2.1.5 疑问与解惑.95

Codis 做者黄东旭:细说分布式 Redis 架构设计和那些踩过的坑 - 架构 - dbaplus 社群:围绕 Data、Blockchain、AiOps 的企业级专业社群。技术大咖、原创干货,天天精品原创文章推送,每周线上技术分享,每个月线下技术沙龙。Redis 是个好东西,但如何平行扩展,如何高可用,是每一个 redis 使用者心中的痛。

Codis 是一个分布式 Redis 解决方案,与官方的纯 P2P 模式不一样,Codis 采用的是 Proxy-based 的方案。今天咱们介绍一下 Codis 以及下一个大版本 RebornDB 的设计,同时会介绍 Codis 在实际应用场景中的一些 tips。最后抛砖引玉,介绍一下我对分布式存储的一些观点和见解。

目录


  • Redis、RedisCluster 和 Codis

  • 咱们更爱一致性

  • Codis 在生产环境中的使用的经验和坑们

  • 对于分布式数据库和分布式架构的一些见解

  • 答疑记录


1Redis,RedisCluster 和 Codis

一、Redis:想必你们的架构中,Redis 已是一个必不可少的部件,丰富的数据结构和超高的性能以及简单的协议,让 Redis 可以很好的做为数据库的上游缓存层。可是咱们会比较担忧 Redis 的单点问题,单点 Redis 容量大小总受限于内存,在业务对性能要求比较高的状况下,理想状况下咱们但愿全部的数据都能在内存里面,不要打到数据库上,因此很天然的就会寻求其余方案。 好比,SSD 将内存换成了磁盘,以换取更大的容量。

更天然的想法是将 Redis 变成一个能够水平扩展的分布式缓存服务,在 Codis 以前,业界只有 Twemproxy,可是 Twemproxy 自己是一个静态的分布式 Redis 方案,进行扩容 / 缩容时候对运维要求很是高,并且很难作到平滑的扩缩容。Codis 的目标其实就是尽可能兼容 Twemproxy 的基础上,加上数据迁移的功能以实现扩容和缩容,最终替换 Twemproxy。从豌豆荚最后上线的结果来看,最后彻底替换了 Twem,大概 2T 左右的内存集群。

二、Redis Cluster  :与 Codis 同期发布正式版的官方 cluster,我认为有优势也有缺点,做为架构师,我并不会在生产环境中使用,缘由有两个:


  • cluster 的数据存储模块和分布式的逻辑模块是耦合在一块儿的,这个带来的好处是部署异常简单,all-in-the-box,没有像 Codis 那么多概念,组件和依赖。可是带来的缺点是,你很难对业务进行无痛的升级。好比哪天 Redis cluster 的分布式逻辑出现了比较严重的 bug,你该如何升级? 除了滚动重启整个集群,没什么好办法。这个比较伤运维。


  • 对协议进行了较大的修改,对客户端不太友好,目前不少客户端已经成为事实标准,并且不少程序已经写好了,让业务方去更换 Redisclient,是不太现实的,并且目前很难说有哪一个 Rediscluster 客户端通过了大规模生产环境的验证,从 HunanTV 开源的 Rediscluster proxy 上能够看得出这个影响仍是蛮大的,不然就会支持使用 cluster 的 client 了。

三、Codis:和 Redis cluster 不一样的是,Codis 采用一层无状态的 proxy 层,将分布式逻辑写在 proxy 上,底层的存储引擎仍是 Redis 自己(尽管基于 Redis2.8.13 上作了一些小 patch),数据的分布状态存储于 zookeeper(etcd) 中,底层的数据存储变成了可插拔的部件。这个事情的好处其实不用多说,就是各个部件是能够动态水平扩展的,尤为无状态的 proxy 对于动态的负载均衡,仍是意义很大的,并且还能够作一些有意思的事情,好比发现一些 slot 的数据比较冷,能够专门用一个支持持久化存储的 server group 来负责这部分 slot,以节省内存,当这部分数据变热起来时,能够再动态的迁移到内存的 server group 上,一切对业务透明。比较有意思的是,在 Twitter 内部弃用 Twmeproxy 后,t 家本身开发了一个新的分布式 Redis 解决方案,仍然走的是 proxy-based 路线。不过没有开源出来。

可插拔存储引擎这个事情也是 Codis 的下一代产品 RebornDB 在作的一件事情。btw,RebornDB 和它的持久化引擎都是彻底开源的,见 https://github.com/reborndb/reborn 和 https://github.com/reborndb/qdb。固然这样的设计的坏处是,通过了 proxy,多了一次网络交互,看上去性能降低了一些,可是记住,咱们的 proxy 是能够动态扩展的,整个服务的 QPS 并不禁单个 proxy 的性能决定(因此生产环境中我建议使用 LVS/HA Proxy 或者 Jodis),每一个 proxy 其实都是同样的。


2咱们更爱一致性

不少朋友问我,为何不支持读写分离,其实这个事情的缘由很简单,由于咱们当时的业务场景不能容忍数据不一致,因为 Redis 自己的 replication 模型是主从异步复制,在 master 上写成功后,在 slave 上是否能读到这个数据是没有保证的,而让业务方处理一致性的问题仍是蛮麻烦的。并且 Redis 单点的性能仍是蛮高的,不像 mysql 之类的真正的数据库,没有必要为了提高一点点读 QPS 而让业务方困惑。这和数据库的角色不太同样。因此,你可能看出来了,其实 Codis 的 HA,并不能保证数据彻底不丢失,由于是异步复制,因此 master 挂掉后,若是有没有同步到 slave 上的数据,此时将 slave 提高成 master 后,刚刚写入的还没来得及同步的数据就会丢失。不过在 RebornDB 中咱们会尝试对持久化存储引擎(qdb)可能会支持同步复制 (syncreplication),让一些对数据一致性和安全性有更强要求的服务能够使用。

说到一致性,这也是 Codis 支持的 MGET/MSET 没法保证本来单点时的原子语义的缘由。 由于 MSET 所参与的 key 可能分不在不一样的机器上,若是须要保证原来的语义,也就是要么一块儿成功,要么一块儿失败,这样就是一个分布式事务的问题,对于 Redis 来讲,并无 WAL 或者回滚这么一说,因此即便是一个最简单的二阶段提交的策略都很难实现,并且即便实现了,性能也没有保证。因此在 Codis 中使用 MSET/MGET 其实和你本地开个多线程 SET/GET 效果同样,只不过是由服务端打包返回罢了,咱们加上这个命令的支持只是为了更好的支持之前用 Twemproxy 的业务。

在实际场景中,不少朋友使用了 lua 脚本以扩展 Redis 的功能,其实 Codis 这边是支持的,但记住,Codis 在涉及这种场景的时候,仅仅是转发而已,它并不保证你脚本操做的数据是否在正确的节点上。好比,你的脚本里涉及操做多个 key,Codis 能作的就是将这个脚本分配到参数列表中的第一个 key 的机器上执行。因此这种场景下,你须要本身保证你的脚本所用到的 key 分布在同一个机器上,这里能够采用 hashtag 的方式。

好比你有一个脚本是操做某个用户的多个信息,如 uid1age,uid1sex,uid1name 形如此类的 key,若是你不用 hashtag 的话,这些 key 可能会分散在不一样的机器上,若是使用了 hashtag(用花括号扩住计算 hash 的区域):{uid1}age,{uid1}sex,{uid1}name,这样就保证这些 key 分布在同一个机器上。这个是 twemproxy 引入的一个语法,咱们这边也支持了。

在开源 Codis 后,咱们收到了不少社区的反馈,大多数的意见是集中在 Zookeeper 的依赖,Redis 的修改,还有为啥须要 Proxy 上面,咱们也在思考,这几个东西是否是必须的。固然这几个部件带来的好处毋庸置疑,上面也阐述过了,可是有没有办法能作得更漂亮。因而,咱们在下一阶段会再往前走一步,实现如下几个设计:


  • 使用 proxy 内置的 Raft 来代替外部的 Zookeeper,zk 对于咱们来讲,其实只是一个强一致性存储而已,咱们其实能够使用 Raft 来作到一样的事情。将 raft 嵌入 proxy,来同步路由信息。达到减小依赖的效果。


  • 抽象存储引擎层,由 proxy 或者第三方的 agent 来负责启动和管理存储引擎的生命周期。具体来讲,就是如今 codis 还须要手动的去部署底层的 Redis 或者 qdb,本身配置主从关系什么的,可是将来咱们会把这个事情交给一个自动化的 agent 或者甚至在 proxy 内部集成存储引擎。这样的好处是咱们能够最大程度上的减少 Proxy 转发的损耗(好比 proxy 会在本地启动 Redis instance)和人工误操做,提高了整个系统的自动化程度。


  • 还有 replication based migration。众所周知,如今 Codis 的数据迁移方式是经过修改底层 Redis,加入单 key 的原子迁移命令实现的。这样的好处是实现简单、迁移过程对业务无感知。可是坏处也是很明显,首先就是速度比较慢,并且对 Redis 有侵入性,还有维护 slot 信息给 Redis 带来额外的内存开销。大概对于小 key-value 为主业务和原生 Redis 是 1:1.5 的比例,因此仍是比较费内存的。

在 RebornDB 中咱们会尝试提供基于复制的迁移方式,也就是开始迁移时,记录某 slot 的操做,而后在后台开始同步到 slave,当 slave 同步完后,开始将记录的操做回放,回放差很少后,将 master 的写入中止,追平后修改路由表,将须要迁移的 slot 切换成新的 master,主从(半)同步复制,这个以前提到过。


3Codis 在生产环境中的使用的经验和坑们

来讲一些 tips,做为开发工程师,一线的操做经验确定没有运维的同窗多,你们一会能够一块儿再深度讨论。

一、关于多产品线部署:不少朋友问咱们若是有多个项目时,codis 如何部署比较好,咱们当时在豌豆荚的时候,一个产品线会部署一整套 codis,可是 zk 共用一个,不一样的 codis 集群拥有不一样的 product name 来区分,codis 自己的设计没有命名空间那么一说,一个 codis 只能对应一个 product name。不一样 product name 的 codis 集群在同一个 zk 上不会相互干扰。

二、关于 zk:因为 Codis 是一个强依赖的 zk 的项目,并且在 proxy 和 zk 的链接发生抖动形成 sessionexpired 的时候,proxy 是不能对外提供服务的,因此尽可能保证 proxy 和 zk 部署在同一个机房。生产环境中 zk 必定要是 >=3 台的奇数台机器,建议 5 台物理机。

三、关于 HA:这里的 HA 分红两部分,一个是 proxy 层的 HA,还有底层 Redis 的 HA。先说 proxy 层的 HA。以前提到过 proxy 自己是无状态的,因此 proxy 自己的 HA 是比较好作的,由于链接到任何一个活着的 proxy 上都是同样的,在生产环境中,咱们使用的是 jodis,这个是咱们开发的一个 jedis 链接池,很简单,就是监听 zk 上面的存活 proxy 列表,挨个返回 jedis 对象,达到负载均衡和 HA 的效果。也有朋友在生产环境中使用 LVS 和 HA Proxy 来作负载均衡,这也是能够的。 Redis 自己的 HA,这里的 Redis 指的是 codis 底层的各个 server group 的 master,在一开始的时候 codis 原本就没有将这部分的 HA 设计进去,由于 Redis 在挂掉后,若是直接将 slave 提高上来的话,可能会形成数据不一致的状况,由于有新的修改可能在 master 中尚未同步到 slave 上,这种状况下须要管理员手动的操做修复数据。后来咱们发现这个需求确实比较多的朋友反映,因而咱们开发了一个简单的 ha 工具:codis-ha,用于监控各个 server group 的 master 的存活状况,若是某个 master 挂掉了,会直接提高该 group 的一个 slave 成为新的 master。 项目的地址是:https://github.com/ngaut/codis-ha

四、关于 dashboard:dashboard 在 codis 中是一个很重要的角色,全部的集群信息变动操做都是经过 dashboard 发起的(这个设计有点像 docker),dashboard 对外暴露了一系列 RESTfulAPI 接口,无论是 web 管理工具,仍是命令行工具都是经过访问这些 httpapi 来进行操做的,因此请保证 dashboard 和其余各个组件的网络连通性。好比,常常发现有用户的 dashboard 中集群的 ops 为 0,就是由于 dashboard 没法链接到 proxy 的机器的缘故。

五、关于 go 环境:在生产环境中尽可能使用 go1.3.x 的版本,go 的 1.4 的性能不好,更像是一个中间版本,尚未达到 production ready 的状态就发布了。不少朋友对 go 的 gc 很有微词,这里咱们不讨论哲学问题,选择 go 是多方面因素权衡后的结果,并且 codis 是一个中间件类型的产品,并不会有太多小对象常驻内存,因此对于 gc 来讲基本毫无压力,因此不用考虑 gc 的问题。

六、关于队列的设计:其实简单来讲,就是不要把鸡蛋放在一个篮子里的道理,尽可能不要把数据都往一个 key 里放,由于 codis 是一个分布式的集群,若是你永远只操做一个 key,就至关于退化成单个 Redis 实例了。不少朋友将 Redis 用来作队列,可是 Codis 并无提供 BLPOP/BLPUSH 的接口,这没问题,能够将列表在逻辑上拆成多个 LIST 的 key,在业务端经过定时轮询来实现(除非你的队列须要严格的时序要求),这样就可让不一样的 Redis 来分担这个同一个列表的访问压力。并且单 key 过大可能会形成迁移时的阻塞,因为 Redis 是一个单线程的程序,因此迁移的时候会阻塞正常的访问。

七、关于主从和 bgsave:codis 自己并不负责维护 Redis 的主从关系,在 codis 里面的 master 和 slave 只是概念上的:proxy 会将请求打到「master」上,master 挂了 codis-ha 会将某一个「slave」提高成 master。而真正的主从复制,须要在启动底层的 Redis 时手动的配置。在生产环境中,我建议 master 的机器不要开 bgsave,也不要轻易的执行 save 命令,数据的备份尽可能放在 slave 上操做。

八、关于跨机房 / 多活:想都别想。codis 没有多副本的概念,并且 codis 多用于缓存的业务场景,业务的压力是直接打到缓存上的,在这层作跨机房架构的话,性能和一致性是很可贵到保证的。

九、关于 proxy 的部署:其实能够将 proxy 部署在 client 很近的地方,好比同一个物理机上,这样有利于减小延迟,可是须要注意的是,目前 jodis 并不会根据 proxy 的位置来选择位置最佳的实例,须要修改。


4对于分布式数据库和分布式架构的一些见解(one more thing)

Codis 相关的内容告一段落。接下来我想聊聊我对于分布式数据库和分布式架构的一些见解。 架构师们是如此贪心,有单点就必定要变成分布式,同时还但愿尽量的透明: P。就 MySQL 来看,从最先的单点到主从读写分离,再到后来阿里的相似 Cobar 和 TDDL,分布式和可扩展性是达到了,可是牺牲了事务支持,因而有了后来的 OceanBase。Redis 从单点到 Twemproxy,再到 Codis,再到 Reborn。到最后的存储早已和最初的面目全非,但协议和接口永存,好比 SQL 和 Redis Protocol。

NoSQL 来了一茬又一茬,从 HBase 到 Cassandra 到 MongoDB,解决的是数据的扩展性问题,经过裁剪业务的存储和查询的模型来在 CAP 上平衡。可是几乎仍是都丢掉了跨行事务(插一句,小米上在 HBase 上加入了跨行事务,不错的工做)。

我认为,抛开底层存储的细节,对于业务来讲,KV,SQL 查询(关系型数据库支持)和事务,能够说是构成业务系统的存储原语。为何 memcached/Redis+mysql 的组合如此的受欢迎,正是由于这个组合,几个原语都能用上,对于业务来讲,能够很方便的实现各类业务的存储需求,能轻易的写出「正确」的程序。可是,如今的问题是数据大到必定程度上时,从单机向分布式进化的过程当中,最难搞定的就是事务,SQL 支持什么的还能够经过各类 mysqlproxy 搞定,KV 就不用说了,天生对分布式友好。

因而这样,咱们就默认进入了一个没有(跨行)事务支持的世界里,不少业务场景咱们只能牺牲业务的正确性来在实现的复杂度上平衡。好比一个很简单的需求:微博关注数的变化,最直白,最正常的写法应该是,将被关注者的被关注数的修改和关注者的关注数修改放到同一个事务里,一块儿提交,要么一块儿成功,要么一块儿失败。可是如今为了考虑性能,为了考虑实现复杂度,通常来讲的作法多是队列辅助异步的修改,或者经过 cache 先暂存等等方式绕开事务

可是在一些须要强事务支持的场景就没有那么好绕过去了(目前咱们只讨论开源的架构方案),好比支付 / 积分变动业务,常见的搞法是关键路径根据用户特征 sharding 到单点 MySQL,或者 MySQLXA,可是性能降低得太厉害。

后来 Google 在他们的广告业务中遇到这个问题,既须要高性能,又须要分布式事务,还必须保证一致性。Google 在此以前是经过一个大规模的 MySQL 集群经过 sharding 苦苦支撑,这个架构的可运维 / 扩展性实在太差。这要是在通常公司,估计也就忍了,可是 Google 可不是通常公司,用原子钟搞定 Spanner,而后在 Spanner 上构建了 SQL 查询层 F1。我在第一次看到这个系统的时候,感受太惊艳了,这应该是第一个能够真正称为 NewSQL 的公开设计系统。因此,BigTable(KV)+F1(SQL)+Spanner(高性能分布式事务支持),同时 Spanner 还有一个很是重要的特性是跨数据中心的复制和一致性保证(经过 Paxos 实现),多数据中心,恰好补全了整个 Google 的基础设施的数据库栈。这样一来,对于 Google,几乎任何类型的业务系统开发起来都很是方便。我想,这就是将来的方向吧,一个可扩展的 KV 数据库做为缓存和简单对象存储,一个高性能支持分布式事务和 SQL 查询接口的分布式关系型数据库,提供表支持。


Spanner 是Google的全球级的分布式数据库 (Globally-Distributed Database) 。Spanner的扩展性达到了使人咋舌的全球级,能够扩展到数百万的机器,数已百计的数据中心,上万亿的行。更给力的是,除了夸张的扩展性以外,他还能同时经过同步复制和多版原本知足外部一致性,可用性也是很好的。冲破CAP的枷锁,在三者之间完美平衡

Spanner是个可扩展,多版本,全球分布式还支持同步复制的数据库。他是Google的第一个能够全球扩展而且支持外部一致的事务。Spanner能作到这些,离不开一个用GPS和原子钟实现的时间API这个API能将数据中心之间的时间同步精确到10ms之内。所以有几个给力的功能:无锁读事务,原子schema修改,读历史数据无block。


5答疑记录

Q1:我没看过 Codis,您说 Codis 没有多副本概念,请问是什么意思?

A1:Codis 是一个分布式 Redis 解决方案,是经过 presharding 把数据在概念上分红 1024 个 slot,而后经过 proxy 将不一样的 key 的请求转发到不一样的机器上,数据的副本仍是经过 Redis 自己保证。

Q2:Codis 的信息在一个 zk 里面存储着,zk 在 Codis 中还有别的做用吗?主从切换为什么不用 sentinel。

A2:Codis 的特色是动态的扩容缩容,对业务透明。zk 除了存储路由信息,同时还做为一个事件同步的媒介服务,好比变动 master 或者数据迁移这样的事情,须要全部的 proxy 经过监听特定 zk 事件来实现能够说 zk 被咱们当作了一个可靠的 rpc 的信道来使用。由于只有集群变动的 admin 时候会往 zk 上发事件,proxy 监听到之后,回复在 zk 上,admin 收到各个 proxy 的回复后才继续。自己集群变动的事情不会常常发生,因此数据量不大。Redis 的主从切换是经过 codis-ha 在 zk 上遍历各个 server group 的 master 判断存活状况,来决定是否发起提高新 master 的命令。

Q3:数据分片,是用的一致性 hash 吗?请具体介绍下,谢谢。

A3:不是,是经过 presharding,hash 算法是 crc32(key)%1024

Q4:怎么进行权限管理?

A4:Codis 中没有鉴权相关的命令,在 reborndb 中加入了 auth 指令。

Q5:怎么禁止普通用户连接 Redis 破坏数据?

A5:同上,目前 Codis 没有 auth,接下来的版本会加入。

Q6:Redis 跨机房有什么方案?

A6:目前没有好的办法,咱们的 Codis 定位是同一个机房内部的缓存服务,跨机房复制对于 Redis 这样的服务来讲,一是延迟较大,二是一致性难以保证,对于性能要求比较高的缓存服务,我以为跨机房不是好的选择。

Q7:集群的主从怎么作(好比集群 S 是集群 M 的从,S 和 M 的节点数可能不同,S 和 M 可能不在一个机房)?

A7:Codis 只是一个 proxy-based 的中间件,并不负责数据副本相关的工做。也就是数据只有一份,在 Redis 内部。

Q8:根据你介绍了这么多,我能够下一个结论,大家没有多租户的概念,也没有作到高可用。能够这么说吧?大家更多的是把 Redis 当作一个 cache 来设计

A8:对,其实咱们内部多租户是经过多 Codis 集群解决的,Codis 更多的是为了替换 twemproxy 的一个项目。高可用是经过第三方工具实现。Redis 是 cache,Codis 主要解决的是 Redis 单点、水平扩展的问题。把 codis 的介绍贴一下: Auto rebalance Extremely simple to use Support both Redis or rocksdb transparently. GUI dashboard & admin tools Supports most of Redis commands. Fully compatible with twemproxy(https://github.com/twitter/twemproxy). Native Redis clients are supported Safe and transparent data migration, Easily add or remove nodes on-demand. 解决的问题是这些。业务不停的状况下,怎么动态的扩展缓存层,这个是 codis 关注的。

Q9:对于 Redis 冷备的数据库的迁移,您有啥经验没有?对于 Redis 热数据,能够经过 migrate 命令实现两个 Redis 进程间的数据转移,固然若是对端有密码,migrate 就不行了(这个我已经给 Redis 官方提交了 patch)。

A9:冷数据咱们如今是实现了完整的 Redissync 协议,同时实现了一个基于 rocksdb 的磁盘存储引擎,备机的冷数据,所有是存在磁盘上的,直接做为一个从挂在 master 上的。实际使用时,3 个 group,keys 数量一致,但其中一个的 ops 是另外两个的两倍,有多是什么缘由形成的?key 的数量一致并不表明实际请求是均匀分布的,不如你可能某几个 key 特别热,它必定是会落在实际存储这个 key 的机器上的。刚才说的 rocksdb 的存储引擎:https://github.com/reborndb/qdb,其实启动后就是个 Redis-server,支持了 PSYNC 协议,因此能够直接当成 Redis 历来用。是一个节省从库内存的好方法。

Q10:Redis 实例内存占比超过 50%,此时执行 bgsave,开了虚拟内存支持的会阻塞,不开虚拟内存支持的会直接返回 err,对吗?

A10:不必定,这个要看写数据(开启 bgsave 后修改的数据)的频繁程度,在 Redis 内部执行 bgsave,实际上是经过操做系统 COW 机制来实现复制,若是你这段时间的把几乎全部的数据都修改了,这样操做系统只能所有完整的复制出来,这样就爆了。

Q11:刚读完,赞一个。能否介绍下 codis 的 autorebalance 实现。

A11:算法比较简单,https://github.com/wandoulabs/codis/blob/master/cmd/cconfig/rebalancer.go#L104。代码比较清楚,code talks:)。其实就是根据各个实例的内存比例,分配 slot 好的

Q12:主要想了解对下降数据迁移对线上服务的影响,有没有什么经验介绍?

A12:其实如今 codis 数据迁移的方式已经很温和了,是一个个 key 的原子迁移,若是怕抖动甚至能够加上每一个 key 的延迟时间。这个好处就是对业务基本没感知,可是缺点就是慢。

文章来源高可用架构订阅号,经做者赞成由 DBA + 社群转发。

做者介绍:黄东旭

  • Ping CAP CTO,开源项目 Codis 的 co-author。

  • 曾在豌豆荚从事 infrastructure 相关的工做,如今在创业公司 PingCAP,方向依然是分布式存储领域 (NewSQL)。

 
   

 


霍泰稳/2.2 给你介绍一个不同的硅谷.98
2.2.1 Uber .98
2.2.2 Coursera.99
2.2.3 Airbnb102
2.2.4 硅谷行带给个人一些影响106
2.2.5 疑问与解惑106

 


金自翔/2.3 解耦的艺术——大型互联网业务系统的插件化改造110
2.3.1 插件化.110
2.3.2 如何处理用户交互115
2.3.3 如何处理数据.115
2.3.4 总结116

解耦的艺术—大型互联网业务系统的插件化改造 | 高可用架构

此文是根据金自翔在【QCON高可用架构群】中的分享内容整理而成,转发请注明出处。

 

金自翔,百度资深研发工程师。在百度负责商业产品的后端架构,包括基础架构和业务架构。本文主要是根据讲师多年经验,针对业界常常碰到的问题,通过分析与实践提出的一种解决方案。

 

在大型系统中,“插件化”是对若干相似的子系统进行深度集成的一种方法,“插件化”的特色是能清晰的划分子系统间的边界,从实现上明确的区分系统中“变”与“不变”的部分。

 

在大的业务系统重构和改造的过程当中,使用“插件化”不但能整合底层数据流,还能同时整合上层的流程和交互,在大规模跨团队集成中提供开发者的灵活性、用户体验的一致性和底层系统的安全性。

 

“插件化”要解决的问题以下图所示

0?wx_fmt=jpeg

 

图中的差别在不一样案例中可能表现为代码思路的差别,用户体验的差别或者是性能的差别。

不管哪一种差别,根本问题在于用天然语言描述的规范文档不够形式化,留下了太多没必要要的自由发挥的空间。

 

“插件化”的目的就是尽可能减小这些空间的存在。下面结合一个具体案例说下如何具体实施插件化。

这个案例是个源码过千万行的业务系统,整个开发团队规模比较大。该系统集成了不少业务产品,用了不少年,用户不少,需求也一直很频繁,是个核心的业务系统。

 

讲师观察过业界一些大的系统,通过大的重构拆分红了若干支持系统和业务系统后,拆分出来的系统分别由(组织架构上)独立的团队负责,这样有效减小了团队内沟通的成本。

 

但正如上图所示,拆分后不可避免的遇到了如下两个问题

 

一、文档

 

人员更替,排期压力,都会形成原有设计意图不能获得贯彻。想靠文档规范和约束,文档和代码同步的代价也很大。

 

尤为是敏捷开发模式下,大量想法没有落实到文档上,初始设计可能不错,但在实施过程当中会越走越偏,留下大量不良的耦合与既有实现,维护成本愈来愈高。之前大团队中经过大规模review能在很大程度上避免这个问题,拆分后跨团队review实施难度很大,基本起不到什么做用。

 

二、碎片化

 

技术架构和业务架构的拆分是同时进行的。整个系统架构拆分后,研发和产品团队也拆分组成了垂直的团队,迭代速度快了不少。

 

可是垂直化不可避免的带来了碎片化的问题。在垂直体系中,每一个产品的流程设计、交互设计有着极大的自主权。产品间的差别愈来愈大,业务流程和用户体验都开始碎片化。

 

碎片化形成用户的学习和使用成本提升,每一个团队都认为本身的设计是最适合本身产品的, 但用户的反馈则是“为啥大家的产品长的都不同呢?用起来好累。” 而后有些用户就不肯意用这样的系统了。

 

碎片化的问题愈来愈严重,开始影响到了整个业务目标的实现。也发如今一些系统中,出现最后老板拍板,把解决碎片化放到最高优先级来解决。

 

消除碎片化最容易想到的方案是在各产品上再抽一层,做一个新系统(后面称其为U系统),把容易碎片化的流程,交互等工做放到这里统一处理,用户只接触U系统,再也不接触各个产品,天然也就没有碎片化的问题。

 

但是细想一想,这方案无非是把问题搬了个地方。由于U系统的需求仍是从各产品来的,原本拆完后各产品能自行实现需求(并行),如今只能把需求提到U系统等排期(串行),U系统极可能成为瓶颈,妨碍业务需求的快速响应。

 

这个方案能保证统一,但丧失了好不容易得到的灵活性,是产品团队不能接受的。

 

最终解决矛盾的方法就是开始提到的插件化

 

插件化相似软件设计中的“依赖注入”,将整个系统分红 “引擎”和“插件”两部分。用“引擎”保证统一,用“插件”提供灵活性。

 

具体实现时,U系统是一套“引擎”(可类比为spring-core这样的框架),自身没有逻辑,只是提供了一组插件规范。

 

引擎能够解析插件,运行插件中指定的逻辑。

 

“插件”由接入的产品提供(可类比为spring的配置文件),插件中指定了产品须要的各类逻辑,可随时更改。当“插件”注入到“引擎”后,就完成了新产品接入U系统的工做。

 

U系统的架构图以下

0?wx_fmt=jpeg

 

 

这个设计的好处是, U系统聚焦在做好引擎上就行,大部分提给U系统的需求能够做成配置,而配置的更改能够交给接入产品来完成。这样U系统和接入的产品彼此解耦,有足够的灵活性。至于碎片化的问题,则经过引擎中“用户交互”和“业务流程”两层来解决。

 

如下详细介绍实现

 

整个U系统由服务、插件、引擎和通讯四大块组成。

 

其中服务由U系统指定接口,业务产品提供具体实现以供调用。目前业务系统基本都是java实现,RPC框架支持U系统直接发布一个jar包,指定每一个接入产品必须提供的一组接口(好比提供基础信息,进行数据校验,提供报表数据等)。每一个产品首先要实现这些服务,而后才能接入U系统。

 

实现服务后,每一个产品会提供一个插件(XML)文件,这个文件包含全部定制化的信息,包括

产品使用的流程

产品提供的服务(地址和接口)

交互界面的DSL(控件)

数据处理(展现、格式化、转化)

报表(从何处取,如何处理)

 

在U系统上传这个插件文件后,系统中就多了一个产品,用户也能看到并使用这个产品。引擎保证了全部插件是能够热插拔的,因此业务变动时只需上传新的插件便可,不用重启和上线,很是方便。

 

下面说一下引擎,引擎是整个系统最核心的模块,插件的的管理、解析和运行都在这里完成。

 

引擎模块是独立开发的,并无采用OSGI的规范实现,而是实现了一套自定义的规范,这是出于如下几点考虑:

 

1.OSGI更多定位在服务的注册、发现、隔离和调用,而U系统中远程RPC已有成熟的框架完成服务发现和治理的工做。至于引擎自身的代码是可控的,采用进程内调用便可,不须要隔离,进程内的依赖管理用Spring就足够了。

 

2.OSGI基本没有交互界面相关的功能,而解析插件提供的用DSL处理交互界面和逻辑是引擎很重要的功能。

 

3.OSGI 的发布采用Bundle方式,能够比较灵活的指定Import和Export功能。但其实并不须要这么灵活,写死引擎提供的接口能够下降使用成本。另外Bundle的构建和发布也没有直接上传XML来的简单。

 

引擎分层以下:

0?wx_fmt=jpeg

 

最底层是基础服务。像帐户、资金、报表这些功能其实很依赖于外部系统,须要将这些外部系统封装成内部的基础服务供上层调用。这里的难点主要是外部系统常常不稳定甚至出错。因此这层设计时要考虑不少容错的方案。

 

好比:

1) 异步化,全部的同步接口异步调用,针对某些错误自动重试。

2)自动超时,监控全部未在必定时间内获得处理的请求

3)对帐,下游系统支持的状况下对每一个请求引入uuid,定时对帐

4)数据修复自动化,可恢复的错误尽可能不要引入人工干预。

 

除此以外,为了稳定起见,引擎的基础服务层会提供本身的服务降级/快速失败功能,以适配没有经过RPC框架提供相似功能的外部系统。

 

基础服务之上是业务流程

 

U系统不容许具体产品自定义业务流程。而是提供若干标准流程由产品在插件中指定。

 

考虑到流程会变更,内部实现上使用了工做流引擎,这样流程变动时的工做量会小不少。虽然技术上可行,但短时间内不会把工做流引擎开发给业务产品定制。

 

统一流程这事儿业务价值很大,由于终于有办法用技术手段防止流程碎片化了。业务产品再没办法偷偷地改流程了,毕竟流程图都在U系统,交互也都在U系统的server上进行,业务方想改也改不了。

 

业务流程之上是自定义逻辑层

 

接入产品是有不少自定义功能,其中至关一部分用xml很难表示,因此容许在配置文件中直接提交代码,引擎动态编译并执行这些代码。

 

在实践中,容许用代码实现的功能大体能够有

 

1)交互界面初始值的获取

2)用户输入的转换、处理

3)系统间交互数据的转换

4)展现界面数据的格式化

 

容许提交代码,很重要的一点就是要处理好安全性,避免提交代码中有错波及到系统的其它部分.

 

这里能够作一个沙盒,让全部自定义代码都在沙盒中运行,沙盒能够保证

1.不一样的沙盒互相不能感知彼此的存在。

2.插件中的代码没法修改沙盒之外(引擎)中的状态。

 

在实际的设计中,引擎制定的接口能够在配置文件中用不一样的语言实现,只须要用<java> <scala> <python>等标签区分实现是哪一种语言便可。

 

固然支持不一样语言会对沙盒机制提出更高的要求,能够采用基于JVM的沙盒,经过区分classloader来实现隔离,也能够考虑引入docker,把沙盒做成一个本机的虚拟环境,这样隔离效果会更好。

 

至于为何提交源代码而不是提交编译好的jar?这主要是由于:

1.要支持脚本语言,提交代码的设计更通用。

2.提交代码能够在更新插件时热编译,发现依赖问题,及时反馈;jar包只能在运行期抛异常,反馈置后。

3.经过本机缓存能够避免屡次编译,做到相同的运行效率。

 

如何处理用户交互

 

交互界面是影响用户体验最大的部分,以前一些产品相似功能的交互界面差异很大,用户会很反感。

 

但这块彻底由引擎做也不合适,由于界面是业务产品最易变的部分,引擎都包下来后续维护成本过高。

推荐的做法是提供控件库,把选择界面元素的自由提供给配置文件,但界面的渲染和逻辑由引擎统一负责。

具体来讲,插件中能够像HTML同样指定文本框,下拉列表等控件,自由地构造界面,但不能自定义css和js,而是由平台统一渲染和校验。

 

假如插件配置中有这么一行

<date key="testDate" title="测试Date" required="true" defaultOffsetDays="2" description="活动开始时间" />

U系统的界面上会渲染出一个日期选择控件,控件的排版和样式由引擎决定,插件不能指定。

 

引擎会作一些基础校验(好比这里须要非空),更高级的有业务含义的校验规则由引擎把用户输入传给产品异步进行。

引擎的控件库包含20多种通用控件,包括<lable><text><date><checkbox>等交互控件,并经过<row>这样的控件提供简单的排版功能,基本已经能够知足须要。

 

若是有特殊的交互需求,也是由引擎开发特殊控件而不是由产品提供,这样在提供灵活性的同时最大程度的保证了前端交互的一致性。

 

从结果来看,由于只提供给产品“知足需求的最小自由”,整个系统交互的用户体验仍是很统一的。

 

如何处理数据

 

为保证数据的一致性,避免用户看到的数据和其它途径不一样。U系统对于产品提供的数据尽可能不落地,而是实时调服务去取。

和前面提到的基础服务同样,这里要考虑到产品服务不可用的状况,因此在界面和流程设计以及实现中都要很当心,避免一个服务不可用影响到其它产品功能的正常使用。

出于性能考虑,统计报表的数据是少数的在引擎落地的冗余数据。

报表数据一般不可修改,因此一致性问题不大。

 

固然极端状况下还可能会存在数据的不一致,所以能够提供一个通知机制来做数据订正,但这不是一个正常的功能,并无在插件中提供出来,只能算是一个后门。

 

这也算是业务系统实际落地时无法做的那么“纯粹”的一个例子。

 

U系统上线后,基本同时达到了设计要求

 

1.开发高效。引擎和插件解耦后,接入产品能够自助修改服务和开发插件,由于引擎可以快速反馈,发现错误的速度比之前更快,总体开发工做量也比之前更小。同时引擎自身没有业务逻辑,工做少了不少,基本上一到两我的就能完成维护工做。

2.体验统一。之前全部前端要统一的地方都是出个规范文档,但愿你们照此执行,但老是渐行渐远。如今这些地方都统一了,很天然的约束住了产品的RD和PM,起到了控制做用。

3.结构清晰。在这套架构下,遇到变动时, RD会很天然的在脑海中将其区分为引擎要做的工做和插件要做的工做。你们的思路和认知统一,跨组的学习代价就小,整个组织架构也能更容易变动。

 

总结

讨论应用架构时,一般的服务化,包括如今很热的微服务更多地聚焦在后端服务的集成上。

 

今天分享的插件化在此基础上进了一步,不但要集成后端服务,同时要集成前端用户能感知到的流程和交互界面。

这个项目的实践代表,这种进一步的集成是可行的,是能兼顾灵活性和一致性的。

插件化的集成方案也有其局限性

好比追求个性化的用户产品,UE和PM的话语权会大不少,在这种场景下实施插件化,流程和UI的部分可能会被千奇百怪的业务需求搞的复杂不少。

但一般的业务系统,一致性每每比特立独行更重要,这种场景下插件化的解决方案仍是比较合适的。

 

想进一步讨论插件化解决方案?或想同群专家进一步高可用架构,可回复arch申请进群。

 
   


沈 剑/2.4 从零开始搭建高可用IM 系统117
2.4.1 什么是IM117
2.4.2 协议设计118
2.4.3 WEB 聊天室.122
2.4.4 IM 典型业务场景126
2.4.5 疑问与解惑126

http://www.52im.net/thread-2768-1-1.html

 


陈宗志/2.5 360 分布式存储系统Bada 的架构设计和应用.129
2.5.1 主要应用场景.129
2.5.2 总体架构130
2.5.3 主要模块131
2.5.4 数据分布策略.132
2.5.5 请求流程133
2.5.6 多机房架构134
2.5.7 FAQ138
2.5.8 疑问与解惑139


张 亮/2.6 新一代分布式任务调度框架:当当Elastic-Job 开源项目
的10 项特性143
2.6.1 为何须要做业(定时任务).143
2.6.2 当当以前使用的做业系统144
2.6.3 Elastic-Job 的来历.144
2.6.4 Elastic-Job 包含的功能145
2.6.5 Elastic-Job 的部署和使用.146
2.6.6 对开源产品的开发理念.147
2.6.7 将来展望148
2.6.8 疑问与解惑149

 


付海军/2.7 互联网DSP 广告系统架构及关键技术解析152
2.7.1 优秀DSP 系统的特色152
2.7.2 程序化购买的特色153
2.7.3 在线广告的核心问题156
2.7.4 在线广告的挑战.156
2.7.5 DSP 系统架构.157
2.7.6 RTB 投放引擎的架构.158
2.7.7 DMP160
2.7.8 广告系统DMP 数据处理的架构.160
2.7.9 用户画像的方法.162
2.7.10 广告行业的反做弊.165
2.7.11 P2P 流量互刷166
2.7.12 CPS 引流做弊167
2.7.13 疑问与解惑168

 


王卫华/2.8 亿级规模的Elasticsearch 优化实战170
2.8.1 索引性能(Index Performance) .170
2.8.2 查询性能(Query Perofrmance) 171
2.8.3 其余173
2.8.4 疑问与解惑174
杨卫华/2.9 微博分布式存储考试题:案例讲解及做业精选179
2.9.1 访问场景179
2.9.2 设计180
2.9.3 sharding 策略180
2.9.4 案例精选181
李 凯/2.10 架构师须要了解的Paxos 原理、历程及实战.184
2.10.1 数据库高可用性难题184
2.10.2 Paxos 协议简单回顾.185
2.10.3 Basic Paxos 同步日志的理论模型186
2.10.4 Multi Paxos 的实际应用.187
2.10.5 依赖时钟偏差的变种Paxos 选主协议简单分析190
2.10.6 疑问与解惑191
温 铭/2.11 OpenResty 的如今和将来193
2.11.1 OpenResty 是什么,适合什么场景下使用.193
2.11.2 某安全公司服务端技术选型的标准194
2.11.3 如何在项目中引入新技术.196
2.11.4 如何入门以及学习的正确方法197
2.11.5 OpenResty 中的测试和调试.199
2.11.6 NginScript 是否会替代OpenResty201
2.11.7 将来重点解决的问题和新增特性.202
2.11.8 开源社区建设203
2.11.9 疑问与解惑.203

OpenResty®

 

最新! OpenResty 1.15.8.3 正式版已发布。

最新! OpenResty 1.17.8.1 RC1 已经发布供测试。

最新! 新博客文章OpenResty 和 Nginx 如何分配和管理内存 已发布。

OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建可以处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

OpenResty® 经过汇聚各类设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师能够使用 Lua 脚本语言调动 Nginx 支持的各类 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发链接的高性能 Web 应用系统。

OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不只仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。

参考 组件 能够知道 OpenResty® 中包含了多少软件。

参考 上路 学习如何从最简单的 hello world 开始使用 OpenResty® 开发 HTTP 业务,或前往 下载 直接获取 OpenResty® 的源代码包开始体验。

 
   

第3 章 电商架构热点专题.205张开涛/3.1 亿级商品详情页架构演进技术解密.2053.1.1 商品详情页2053.1.2 商品详情页发展史2093.1.3 遇到的一些问题和解决方案2203.1.4 总结2283.1.5 疑问与解惑229杨 超/3.2 大促系统全流量压测及稳定性保证——京东交易架构.2323.2.1 交易系统的三个阶段2323.2.2 交易系统的三层结构2333.2.3 交易系统的访问特征2343.2.4 应对大促的第1 步:全链路全流量线上压测.2343.2.5 应对大促的第2 步:根据压力表现进行调优.2373.2.6 异步和异构2403.2.7 应对大促的第3 步:分流与限流2423.2.8 应对大促的第4 步:容灾降级.2443.2.9 应对大促的第5 步:完善监控.2453.2.10 疑问与解惑246吕 毅/3.3 秒杀系统架构解密与防刷设计.2483.3.1 抢购业务介绍.2483.3.2 具体抢购项目中的设计.2493.3.3 如何解耦先后端压力2503.3.4 如何保证商品库的库存可靠2523.3.5 如何与第三方多方对帐.2543.3.6 项目总结2553.3.7 疑问与解惑255王富平/3.4 Lambda 架构与推荐在电商网站实践.2573.4.1 Lambda 架构2573.4.2 1 号店推荐系统实践2603.4.3 Lambda 的将来2623.4.4 思考2633.4.5 疑问与解惑263杨 硕/3.5 某公司线上真实流量压测工具构建.2653.5.1 为何要开发一个通用的压测工具2653.5.2 常见的压测工具.2663.5.3 构建本身的压测工具2663.5.4 疑问与解惑271第4 章 容器与云计算.273陈 飞/4.1 微博基于Docker 容器的混合云迁移实战.2734.1.1 为何要采用混合云的架构2734.1.2 跨云的资源管理与调度.2754.1.3 容器的编排与服务发现.2784.1.4 混合云监控体系.2844.1.5 前进路上遇到的那些坑.2864.1.6 疑问与解惑286高 磊/4.2 互联网金融创业公司Docker 实践2874.2.1 背景介绍2874.2.2 容器选型2874.2.3 应用迁移2884.2.4 弹性扩容2914.2.5 将来规划2954.2.6 疑问与解惑295高永超/4.3 使用开源Calico 构建Docker 多租户网络.2974.3.1 PaaS 平台的网络需求.2974.3.2 使用Calico 实现Docker 的跨服务器通信.2984.3.3 利用Profile 实现ACL3014.3.4 性能测试3064.3.5 Calico 的发展3084.3.6 疑问与解惑309彭哲夫/4.4 解析Docker 在芒果TV 的实践之路3104.4.1 豆瓣时期3104.4.2 芒果TV 的Nebulium Engine .3114.4.3 Project Eru .3124.4.4 细节3134.4.5 网络3144.4.6 存储3154.4.7 Scale3164.4.8 资源分配和集群调度3164.4.9 服务发现和安全.3174.4.10 实例3174.4.11 总结3184.4.12 疑问与解惑318王关胜/4.5 微博基于Docker 的混合云平台设计与实践3234.5.1 微博的业务场景及混合云背景.3234.5.2 三大基础设施助力微博混合云.3264.5.3 微博混合云DCP 系统设计核心:自动化、弹性调度3284.5.4 引入阿里云做为第3 机房,实现弹性调度架构3304.5.5 大规模集群操做自动化.3314.5.6 不怕峰值事件.332第5 章 运维保障333王 康/5.1 360 如何用QConf 搞定两万以上服务器的配置管理.3335.1.1 设计初衷3335.1.2 总体认识3345.1.3 架构介绍3355.1.4 QConf 服务端3365.1.5 QConf 客户端3365.1.6 QConf 管理端3405.1.7 其余3415.1.8 疑问与解惑343尤 勇/5.2 深度剖析开源分布式监控CAT3475.2.1 背景介绍3475.2.2 总体设计3485.2.3 客户端设计3495.2.4 服务端设计3525.2.5 总结感悟357杨尚刚/5.3 单表60 亿记录等大数据场景的MySQL 优化和运维之道3595.3.1 前言3595.3.2 数据库开发规范.3605.3.3 数据库运维规范.3635.3.4 性能优化3685.3.5 疑问与解惑375秦 迪/5.4 微博在大规模、高负载系统问题排查方法3795.4.1 背景3795.4.2 排查方法及线索.3795.4.3 总结3845.4.4 疑问与解惑385秦 迪/5.5 系统运维之为何每一个团队存在大量烂代码3875.5.1 写烂代码很容易.3875.5.2 烂代码终究是烂代码3885.5.3 重构不是万能药.3925.5.4 写好代码很难.3935.5.5 悲观的结语394秦 迪/5.6 系统运维之评价代码优劣的方法3955.6.1 什么是好代码.3955.6.2 结语4035.6.3 参考阅读403秦 迪/5.7 系统运维之如何应对烂代码4045.7.1 改善可维护性.4045.7.2 改善性能与健壮性4095.7.3 改善生存环境.4125.7.4 我的感想414第6 章 大数据与数据库415王 劲/6.1 某音乐公司的大数据实践.4156.1.1 什么是大数据.4156.1.2 某音乐公司大数据技术架构4186.1.3 在大数据平台重构过程当中踩过的坑4256.1.4 后续的持续改进.430王新春/6.2 实时计算在点评.4316.2.1 实时计算在点评的使用场景4316.2.2 实时计算在业界的使用场景4326.2.3 点评如何构建实时计算平台4336.2.4 Storm 基础知识简单介绍.4346.2.5 如何保证业务运行的可靠性4366.2.6 Storm 使用经验分享4386.2.7 关于计算框架的后续想法4426.2.8 疑问与解惑442王卫华/6.3 百姓网Elasticsearch 2.x 升级之路.4466.3.1 Elasticsearch 2.x 变化4466.3.2 升级之路4486.3.3 优化或建议4516.3.4 百姓之道4526.3.5 后话:Elasticsearch 5.04536.3.6 升级2.x 版本成功,5.x 版本还会远吗454董西成 张虔熙/6.4 Hadoop、HBase 年度回顾4576.4.1 Hadoop 2015 技术发展4576.4.2 HBase 2015 年技术发展4606.4.3 疑问与解惑466常 雷/6.5 解密Apache HAWQ——功能强大的SQL-on-Hadoop 引擎.4696.5.1 HAWQ 基本介绍4696.5.2 Apache HAWQ 系统架构.4726.5.3 HAWQ 中短时间规划.4796.5.4 贡献到Apache HAWQ 社区4796.5.5 疑问与解惑480萧少聪/6.6 PostgresSQL HA 高可用架构实战.4826.6.1 PostgreSQL 背景介绍.4826.6.2 在PostgreSQL 下如何实现数据复制技术的HA 高可用集群4836.6.3 Corosync+Pacemaker MS 模式介绍4846.6.4 Corosync+Pacemaker M/S 环境配置4856.6.5 Corosync+Pacemaker HA 基础配置4886.6.5 PostgreSQL Sync 模式当前的问题4926.6.6 疑问与解惑492王晶昱/6.7 从NoSQL 历史看将来.4956.7.1 前言4956.7.2 1970 年:We have no SQL4966.7.3 1980 年:Know SQL 4976.7.4 2000 年:No SQL .5026.7.5 2005 年:不只仅是SQL 5046.7.6 2013 年:No,SQL .5056.7.7 阿里的技术选择.5056.7.8 疑问与解惑506杨尚刚/6.8 MySQL 5.7 新特性大全和将来展望.5086.8.1 提升运维效率的特性5086.8.2 优化器Server 层改进.5116.8.3 InnoDB 层优化5136.8.4 将来发展5176.8.5 运维经验总结.5186.8.6 疑问与解惑519谭 政/6.9 大数据盘点之Spark 篇5216.9.1 Spark 的特性以及功能5216.9.2 Spark 在Hulu 的实践.5256.9.3 Spark 将来的发展趋势5286.9.4 参考文章5306.9.5 疑问与解惑530萧少聪/6.10 从Postgres 95 到PostgreSQL 9.5:新版亮眼特性5326.10.1 Postgres 95 介绍5326.10.2 PostgresSQL 版本发展历史5336.10.3 PostgresSQL 9.5 的亮眼特性5346.10.4 PostgresSQL 还能够作什么5446.10.5 疑问与解惑547毕洪宇/6.11 MongoDB 2015 回顾:全新里程碑式的WiredTiger 存储引擎5516.11.1 存储引擎的发展5516.11.2 复制集改进.5556.11.3 自动分片机制5566.11.4 其余新特性介绍5566.11.5 疑问与解惑.558王晓伟/6.12 基于Xapian 的垂直搜索引擎的构建分析5616.12.1 垂直搜索的应用场景5616.12.2 技术选型.5636.12.3 垂直搜索的引擎架构5646.12.4 垂直搜索技术和业务细节.5666.12.5 疑问与解惑568第7 章 安全与网络572郭 伟/7.1 揭秘DDoS 防御——腾讯云大禹系统5727.1.1 有关DDoS 简介的问答.5747.1.2 有关大禹系统简介的问答5757.1.3 有关大禹系统硬件防御能力的问答5767.1.4 有关算法设计的问答5777.1.5 大禹和其余产品、技术的区别.578冯 磊 赵星宇/7.2 App 域名劫持之DNS 高可用——开源版HttpDNS 方案详解5807.2.1 HttpDNSLib 库组成.5817.2.2 HttpDNS 交互流程5827.2.3 代码结构5837.2.4 开发过程当中的一些问题及应对.5867.2.5 疑问与解惑593马 涛/7.3 CDN 对流媒体和应用分发的支持及优化5957.3.1 CDN 系统工做原理.5957.3.2 网络分发过程当中ISP 的影响6027.3.3 防盗链.6037.3.4 内容分发系统的问题和应对思路6047.3.5 P2P 穿墙打洞6077.3.6 疑问与解惑609马 涛/7.4 HTTPS 环境使用第三方CDN 的证书难题与最佳实践611蒋海滔/7.5 互联网主要安全威胁分析及应对方案6137.5.1 互联网Web 应用面临的主要威胁6137.5.2 威胁应对方案.6167.5.3 疑问与解惑624