1 问题背景

分布式缓存一般被定义为一个数据集合,它将数据分布(或分区)于任意数目的集群节点上。集群中的一个具体节点负责缓存中的一部分数据,整体对外提供统一的访问接口[1]。分布式缓存一般基于冗余备份机制实现数据高可用,又被称为内存数据网格(IMDG, in-memory data grid)。在云平台飞速发展的今天,作为提升应用性能的重要手段,分布式缓存技术在工业界得到了越来越广泛的关注和研发投入[2]。弹性缓存平台[3]是分布式缓存集群在云计算场景下的新形态,其强调集群的动态扩展性与高可用性。动态扩展性表达了缓存平台可提供透明的服务扩展的能力,高可用性则表达了缓存平台可以容忍节点失效。

Tair是阿里巴巴集团自研的弹性缓存/存储平台,在内部有着大量的部署和使用。Tair的核心组件是一个高性能、可扩展、高可靠的NoSQL存储系统。目前支持MDB、LDB、RDB等存储引擎。其中MDB是类似Memcached的内存存储引擎,LDB是使用LSM Tree的持久化磁盘KV存储引擎,RDB是支持Queue、Set、Maps等数据结构的内存及持久化存储引擎。

Tair的数据分片和路由算法采用了Amazon于2007年提出的一种改进的一致性哈希算法[4]。该算法将整个哈希空间分为若干等大小的Q份数据分区(也称为虚拟节点,Q>>N,N为缓存节点数),每个缓存节点依据其处理能力分配不同数量的数据分区。客户端请求的数据Key值经哈希函数映射至哈希环上的位置记为token,token值再次被哈希映射为某一分区标识。得到分区标识后,客户端从分区服务器映射表中查询存放该数据分区的缓存节点后进行数据访问。使用该算法对相同数据Key进行计算,其必然会被映射到固定的DataServer上,如图:

此时DataServer单节点的读写性能便成了单数据Key的读写性能瓶颈,且无法通过水平扩展节点的方式来解决。由于阿里巴巴集团内部电商系的促销活动天然的存在热点数据,所以要增强整个弹性缓存/存储平台的稳定性和服务能力,就必须提升热点数据的读写能力,使其能做到水平扩展。

2 解决方案

解决方案分为三部分:热点识别、读热点方案和写热点方案。

其中读写热点方案都是以服务端能对热点访问进行精准的识别为前提的。另外对于可以提前预知热点Key的情况,也提供相应的客户端API以支持特定数据Key或者特定Namespace的所有数据Key预先标记为热点Key的能力。

2.1 DataServer上的热点统计过程

DataServer收到客户端的请求后,由每个具体处理请求的工作线程(Worker Thread)进行请求的统计。工作线程用来统计热点的数据结构均为ThreadLocal模式的数据结构,完全无锁化设计。热点识别算法使用精心设计的多级加权LRU链和HashMap组合的数据结构,在保证服务端请求处理效率的前提下进行请求的全统计,支持QPS热点和流量热点(即请求的QPS不大但是数据本身过大而造成的大流量所形成的热点)的精准识别。每个采样周期结束时,工作线程会将统计的数据结构转交到后台的统计线程池进行分析处理。统计工作异步在后台进行,不抢占正常的数据请求的处理资源。

2.2 读热点方案

2.2.1 服务端设计

原始Tair的数据访问方式是先进行Hash(Key)%BucketCount的计算,得出具体的数据存储Bucket,再检索数据路由表找到该Bucket所在的DataServer后对其进行读写请求的。所以相同Key的读写请求必然落在固定的DataServer上,且无法通过水平扩展DataServer数量来解决。

本方案通过在DataServer上划分一块HotZone存储区域的方式来解决热点数据的访问。该区域存储当前产生的所有读热点的数据,由客户端配置的缓存访问逻辑来处理各级缓存的访问。多级缓存架构如下:

所有DataServer的HotZone存储区域之间没有权重关系,每个HotZone都存储相同的读热点数据。客户端对热点数据Key的请求会随机到任意一台DataServer的HotZone区域,这样单点的热点请求就被散列到多个节点乃至整个集群。

针对上面的技术我特意整理了一下,有很多技术不是靠几句话能讲清楚,所以干脆找朋友录制了一些视频,很多问题其实答案很简单,但是背后的思考和逻辑不简单,要做到知其然还要知其所以然。如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java进阶群:680130298,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

  • 具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。

  • 在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。

  • 如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的可以加群。

2.2.2客户端设计

2.2.2.1 客户端逻辑

当客户端在第一次请求前初始化时,会获取整个Tair集群的节点信息以及完整的数据路由表,同时也会获取配置的热点散列机器数(即客户端访问的HotZone的节点范围)。随后客户端随机选择一个HotZone区域作为自身固定的读写HotZone区域。在DataServer数量和散列机器数配置未发生变化的情况下,不会改变选择。即每个客户端只访问唯一的HotZone区域。

客户端收到服务端反馈的热点Key信息后,至少在客户端生效N秒。在热点Key生效期间,当客户端访问到该Key时,热点的数据会首先尝试从HotZone节点进行访问,此时HotZone节点和源数据DataServer节点形成一个二级的Cache模型。客户端内部包含了两级Cache的处理逻辑,即对于热点数据,客户端首先请求HotZone节点,如果数据不存在,则继续请求源数据节点,获取数据后异步将数据存储到HotZone节点里。使用Tair客户端的应用常规调用获取数据的接口即可,整个热点的反馈、识别以及对多级缓存的访问对外部完全透明。HotZone缓存数据的一致性由客户端初始化时设置的过期时间来保证,具体的时间由具体业务对缓存数据不一致的最大容忍时间来决定。

客户端存储于本地的热点反馈过期后,数据Key会到源DataServer节点读取。如果该Key依旧在服务端处于热点状态,客户端会再次收到热点反馈包。因为所有客户端存储于本地的热点反馈信息的失效节奏不同,所以不会出现同一瞬间所有的请求都回源的情况。即使所有请求回源,也仅需要回源读取一次即可,最大的读取次数仅为应用机器数。若回源后发现该Key已不是热点,客户端便回到常规的访问模式。

2.2.2.2 散列比和QPS偏差的关系

设集群普通QPS为 C,热点QPS为 H,机器数为 N,则每台机器QPS为:

A=(C+H)/N
复制代码

则普通机器QPS偏差比为:

P_c=(C/N)/A=(C/N)/((C+H)/N)=C/(C+H) ,当 H=0 时,P_c=1
复制代码

则热点机器偏差比为:

P_h=(C/N+H)/A=(C/N+H)/((C+H)/N)=(C+HN)/(C+H) ,当 H=0 时,P_h=1
复制代码

进行散列后,设散列机器数为 M,则热点机器偏差比为:

P_(h')=(C/N+H/M)/A=(C/N+H/M)/((C+H)/N)=(CM+HN)/(M(C+H))
复制代码

设散列比为 K,即 M=KN,则有:

P_(h')=(CM+HN)/(M(C+H))=(CKN+HN)/(KN(C+H))=(CK+H)/(K(C+H)),当 K=1 时, P_(h')=1
复制代码

2.3 写热点方案

2.3.1 服务端设计

2.3.1.1 处理方式

对于写热点,因为一致性的问题,难以使用多级缓存的方式来解决。如果采用写本地Cache,再异步更新源DataServer的方案。那么在Cache写入但尚未更新的时候,如果业务机器宕机,就会有已写数据丢失的问题。同时,本地 Cache会导致进行数据更新的某应用机器当前更新周期内的修改对其他应用机器不可见,从而延长数据不一致的时间。故多级Cache的方案无法支持写热点。最终写热点采用在服务端进行请求合并的方式进行处理。

热点Key的写请求在IO线程被分发到专门的热点合并线程处理,该线程根据Key对写请求进行一定时间内的合并,随后由定时线程按照预设的合并周期将合并后的请求提交到引擎层。合并过程中请求结果暂时不返回给客户端,等请求合并写入引擎成功后统一返回。这样做不会有一致性的问题,不会出现写成功后却读到旧数据,也避免了LDB集群返回成功,数据并未落盘的情况(假写)。具体的合并周期在服务端可配置,并支持动态修改生效。

2.3.2 客户端设计

写热点的方案对客户端完全透明,不需要客户端做任何修改。

2.3.3 性能指标

LDB集群实际压测效果为单Key合并能做到单Key百万的QPS(1ms合并,不限制合并次数),线上实际集群为了尽可能保证实时性,均采用了最大0.1ms以及单次最大合并次数为100次的限制。这样单Key在引擎层的最大落盘QPS就能控制在10000以下(而合并的QPS则取决于应用的访问频率)。Tair服务端的包处理是完全异步化的,进行热点请求的合并操作并不阻塞对其他请求的处理。唯一的影响就是增大客户端对热点key的写请求的RT. 按照现在的配置,最坏情况下,客户端的热点key的写操作会增大0.1ms,这个影响是微乎其微的。

淘宝架构师为你揭秘2017双十一分布式缓存服务Tair相关推荐

  1. 2017双11技术揭秘—分布式缓存服务Tair的热点数据散列机制

    摘要: Tair是阿里巴巴集团自研的弹性缓存/存储平台,在内部有着大量的部署和使用.Tair的核心组件是一个高性能.可扩展.高可靠的NoSQL存储系统.目前支持MDB.LDB.RDB等存储引擎.本文基 ...

  2. 【成为架构师课程系列】高性能系统设计之分布式缓存

    缓存:数据库成为瓶颈后,动态数据的查询要如何加速? 通过前面数据库篇的学习,你已经了解了在高并发大流量下,数据库层的演进过程以及库表设计上的考虑点.你的垂直电商系统在完成了对数据库的主从分离和分库分表 ...

  3. 淘宝App惊现“内测版本弹屏”P0级事故!5张淘宝架构PPT,剖析事故始末

    点击"技术领导力"关注∆  每天早上8:30推送 作者| Mr.K   编辑| Emma 来源| 技术领导力(ID:jishulingdaoli) 老K跟朋友开玩笑:今天的心情和手 ...

  4. 「优知学院」淘宝架构的前世今生(下)

    " 淘宝技术架构前世今生就是一部架构活教材,今天仍然由陈睿mikechen为大家解读淘宝架构. 我稍微把前面淘宝架构的三个阶段简短总结: 淘宝1.0 采用LAMP mysql读写操作 淘宝2 ...

  5. 副业行业之:淘宝退货师套路,勿操作

    今天给大家揭秘个副业套路 淘宝退货师的套路 目前据我所知还有一大部分人在操作这个创业项目 本期尉迟站仅做揭秘,避免副业路上的[坑] 揭秘副业行业之:淘宝退货师套路,仅揭秘勿操作 今天给大家揭秘个副业套 ...

  6. GaussDB(for MySQL)如何快速创建索引?华为云数据库资深架构师为您揭秘

    摘要:云服务环境下,如何解决客户基于大量数据创建索引的性能问题,成为云服务厂商的一个挑战.华为云GaussDB(for MySQL)通过引入并行创建索引技术,很好地解决了批量索引创建和临时添加索引等性 ...

  7. 听听【八年阿里架构师】怎样讲述Dubbo和Spring Cloud微服务架构

    微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业 ...

  8. 阿里顶级架构师倾情推荐:国内首本大型分布式架构笔记《凤凰架构》

    前言 随着IT系统复杂度不断增加,无论是为了降低团队的知识负载,还是为了最大化利用云原生的弹性能力,分布式架构已经成为处理新一代复杂系统的默认架构模式.但它的引入也同样:大幅提高了架构的复杂性,导致系 ...

  9. 微服务架构师封神之路02-为你的微服务应用添加日志

    微服务架构师封神之路02-为你的微服务应用添加日志 关于Kubernetes日志架构 我们的目标 helloworld project 项目结构 pom.xml Dockerfile AppMain. ...

最新文章

  1. 索赔cs1.6最新服务器,成功解决CS1.6刷不出服务器
  2. stm32如何执行软复位_常见的单片机复位方式及其原理分析
  3. python中全局变量和局部变量详解_Python全局变量与局部变量详解
  4. Linux命令工作中常用的总结
  5. 数据结构与算法--丑数
  6. html页面通过特殊链接:打电话,发短信,发邮件详细教程
  7. 【安全】LDAP是轻量目录访问协议,英文全称是Lightweight Directory Access Protocol
  8. ionic4 ios打开appstore 跳转第三方app
  9. igm焊接机器人基本操作_焊接机器人编程与操作
  10. xp母盘制作流程+QQDLL修改和系统文件DLL修改(转)
  11. magick 包: 在R中进行高级图片处理
  12. 拉钩网前端项目实战05
  13. Mac运行Pycharm崩溃
  14. 多个数据表格合并计算计算机,多个excel表格某个数据合计-Excel怎么才能快速将几个表的某一列数据求和在一个......
  15. Win10 64bit 下 Oracle 11g的下载与安装+PLSQL的安装 (超级详细)
  16. 用Python打造属于自己的“今日头条” | 一个非常适合练手的全栈项目
  17. linux hosts的allow和deny
  18. Values in v:2 index key pattern cannot be of type object
  19. javax.net.ssl.SSLException 两种解决方法 链接https接口
  20. 研究生自救-写论文篇

热门文章

  1. ctypes python_Python使用Ctypes与C/C++
  2. Keil C51软件的使用教程
  3. 关于堆空间溢出的错误解决办法
  4. js最简单数组去重_js简单数组去重
  5. django 类取消csrf_Django之Form组件详解、图片上传及定制
  6. python中变量不需要事先声明_python 变量搜寻顺序法则LEGB之E注意事项
  7. opencv轻松入门面向python下载_OpenCV轻松入门:面向Python
  8. 通达信服务器维修点查询,通达信验证服务器数据库修改
  9. mac android studio 打不开adb,Android-Macbook ADB无法打开
  10. java通用日志记录_JAVA实现通用日志记录方法