[缓存 - tair] tair的基本知识点和架构设计

1. Tair的基本认识

github - 中文主页
在这里插入图片描述
阿里巴巴的Tair(Tair数据库)是一种分布式存储系统,旨在为大规模数据存储和访问提供高性能、可靠性和可扩展性的解决方案。提供快速访问的内存(MDB引擎)/持久化(LDB引擎)存储服务,基于高性能、高可用的分布式集群架构,满足读写性能要求高及容量可弹性伸缩的业务需求。

2. 系统架构

在这里插入图片描述
在这里插入图片描述
一个Tair集群主要包括3个必选模块:configserver、dataserver和client,通常情况下一个集群包含2台configserver及多台dataserver。
configserver(中心控制节点)

  • 两台configserver互为备份
  • 通过维持与dataserver之间的心跳获知集群中存活可用的dataserver节点信息
  • 构建数据在集群中的分布信息(对照表)
  • 提供数据分布表的查询服务
  • 调度dataserver之间的数据迁移、复制

dataserver (服务节点)

  • 负责数据存储,提供存储引擎
  • 按照configserver的指示完成数据的复制和迁移工作
  • 接受client发起的put/get/remove等操作

client

  • 启动的时候从configserver获取数据分布信息,根据数据分布信息和相应的dataserver交互完成用户的请求。
  • 提供访问tair的API
  • 流量控制
  • 更新并缓存数据分布表

2.1 分布式架构

  • 采用分布式集群架构,具备自动容灾及故障迁移能力。
  • 支持负载均衡,数据均匀分布。
  • 支持弹性扩展系统的存储空间及吞吐性能,突破海量数据高 QPS 性能瓶颈。

负载均衡算法

一致性Hash算法,hash(Key)% bucketCount 得到bucket【负载均衡和数据迁移的基本单位】,ConfigServer建立bucket与dataServer的路由表,指导客户端读写数据

其中,当数据节点发生变化时,ConfigServer会重新构建路由表,构建依据两个原则:

  • 数据在新表中均衡地分布到所有节点上
  • 尽可能地保持现有的对照关系
    具体生成路由表有两种策略:一种是负载均衡优先;一种是位置安全优先

分布式处理

Configserver 负责虚拟节点的选主,同时调度 Dataserver 之间的数据迁移、复制:对于多备份的情况,Tair涉及客户端的读写请求均和主虚拟节点进行交互,从虚拟节点均作为备份。当主虚拟节点出现故障不可用时,ConfigServer会重新指定一个从虚拟节点,升级为主虚拟节点,对外提供服务,并指定一个新的从虚拟节点,以确保数据的备份数;当从虚拟节点出现故障不可用时,configserver会重新为其指定一个从虚拟节点,在持久化模式下,会将故障的节点的数据复制到新的从虚拟节点上。因此,多备份的关联表在构建时需要尽可能保证各个节点作为主节点的个数相近。

3. 基本特点和功能分析

  1. 分布式架构:Tair采用分布式架构,将数据存储在多个节点上,以实现数据的高可用性和容错性。这使得Tair能够处理大规模数据,并提供快速的读写访问。
  2. 多种数据模型:Tair支持多种数据模型,包括键值(Key-Value)、列表(List)、哈希(Hash)、集合(Set)和有序集合(Sorted Set),以满足不同应用场景的需求。
  3. 数据持久化:Tair支持数据持久化存储,可以将数据写入磁盘以保证数据的安全性和可靠性。
  4. 高性能:Tair具有优化的读写性能,通过将数据分布到多个节点上并实现负载均衡,实现了高并发和低延迟的数据访问。
  5. 可扩展性:Tair支持水平扩展,可以根据需求增加节点以扩展存储容量和处理能力,以适应不断增长的数据量和用户访问量。
  6. 数据一致性:Tair通过使用一致性哈希算法和复制机制来确保数据的一致性和可用性。它采用主从复制方式,将数据复制到多个节点上,以实现容错和高可用性。
  7. 实时监控和管理:Tair提供了实时监控和管理工具,以便管理员可以监控和管理集群的状态、性能和健康状况,从而进行及时的故障排除和性能优化。

4. 使用场景分析

4.1 适合使用的场景

  1. 缓存:Tair 作为高性能的分布式存储系统,可以用作缓存层,提供快速的数据访问和响应。它可以减轻后端数据库的负载,加速数据检索,并提高系统的吞吐量和响应速度。
  2. 会话管理:Tair可用于管理用户会话数据,如登录状态、购物车内容等。通过将会话数据存储在Tair中,可以实现会话的高可用性和分布式访问,并支持快速的会话检索和更新。
  3. 分布式配置存储:将配置信息存储在Tair中,可以方便地进行配置的动态管理和更新,并确保配置在分布式环境中的一致性和可用性。
  4. 计数器和排行榜:Tair提供了集合和有序集合等数据类型,适合用于实现计数器和排行榜功能。例如,可以使用Tair来实时统计用户的点击次数、点赞数量,并根据排行榜数据进行排序和展示。
  5. 队列和消息系统:Tair的列表数据类型可用于实现队列和消息系统。通过将消息存储在Tair列表中,可以实现消息的持久化和分布式处理,支持可靠的消息传递和异步处理。
  6. 大规模数据存储和访问:Tair的分布式架构和可扩展性使其适用于大规模数据存储和访问的场景。无论是存储海量用户数据、物联网设备数据还是大数据分析结果,Tair都可以提供高性能和可靠的存储解决方案。

4.2 不适合使用的场景

  1. 复杂的关系型数据:如果数据之间存在复杂的关系和复杂查询需求可能,关系型数据库更适合。
  2. 数据一致性要求高的场景:尽管Tair采用了主从复制和一致性hash等机制来确保数据的一致性,但在一些对数据要求非常高的场景中,例如金融交易系统或者关键业务系统,可能需要使用具备更强一致性保证的数据库系统。
  3. 复杂的分布式事务:如果应用程序需要进行复杂的分布式事务管理,例如跨多个数据源的事务操作和回滚,Tair的分布式事务能力可能相对有限。在这种情况下,可能需要考虑使用其他专门支持分布式事务的数据库或分布式事务管理系统。
  4. 存储大型多媒体文件:Tair适用于存储较小的键值数据,但不适合存储大型的多媒体文件,例如视频文件或大型图片。对于这些情况,更适合使用专门的分布式文件系统或对象存储服务。
适合tair不适合tair
数据规模较大、冷热数据显著的业务场景使用复杂数据结构(map/set),map/set中元素很多(1000以上)
不能容忍数据丢失对单一Key频繁更新,即读写比例很低,例如发号器
value在KB级别及以下热点数据不均匀
使用复杂数据结构map/set的value元素较少(1000以下)value超过1M的
读写比例高,对单一Key更新不频繁

5. 与redis的区别

  1. 数据模型:Tair和Redis的最大区别之一是数据模型。Tair支持多种数据类型,包括键值、列表、哈希、集合和有序集合,提供了更丰富的数据结构。而Redis主要以键值存储为主,支持更简单的数据结构,如字符串、列表、哈希、集合和有序集合。
  2. 数据持久化:在数据持久化方面,Tair和Redis也有不同的方法。Tair支持数据的持久化存储,可以将数据写入磁盘以确保数据的安全性和可靠性。Redis则提供了多种数据持久化选项,包括将数据快照存储到磁盘、写入日志文件以及使用AOF(Append-Only File)日志。
  3. 分布式架构:Tair和Redis都支持分布式架构,将数据存储在多个节点上以实现高可用性和可扩展性。但在分布式路由和负载均衡方面,Tair采用了一致性哈希算法和复制机制,而Redis使用了基于槽(slot)的分片机制
  4. 一致性和事务支持:在一致性和事务支持方面,Tair相对于Redis更加注重数据一致性和分布式事务。Tair通过主从复制和一致性哈希等机制确保数据的一致性,并提供了分布式事务的支持。Redis在一些特殊情况下可能存在数据一致性的问题,并且其事务机制是基于乐观锁(optimistic locking)实现的。
  5. 生态系统和扩展性:Redis拥有非常活跃和丰富的开发社区,具有大量的扩展和插件,支持多种编程语言的客户端库。它在缓存、消息队列、发布/订阅等场景中非常流行。Tair作为阿里巴巴的内部产品,更加定位于满足大规模数据存储和访问的需求,并且与阿里巴巴的其他产品和服务紧密集成。

6. 系统的高可用性和可靠性保证

6.1 系统可用性

分布式集群架构,服务端实现负载均衡,结合自动数据迁移机制,可实现服务的自动容灾,保证服务不中断

轻量化中心节点:ConfigServer存在单点故障的风险,整个集群服务都依赖于ConfigServer的正常工作,但Tair将其轻量化,在DataServer没有发生变化时,ConfigServer不可用对集群服务不会造成影响;仅当客户端需要初始化,或是DataServer发生变化时,会导致客户端无法工作或是请求数据失败

请求转发、临时路由表等保证数据迁移时的可用性

6.2 系统可靠性

支持多副本,且对所有存储引擎都有效,副本个数可配

自动数据复制:当数据写入一个主节点后,主节点会根据路由表自动将数据写入到其他备份节点

6.3 解决数据同步/迁移时的一致性问题

通过代理解决:对于正常的数据迁移来说,假设桶2,3,4的数据从DataServer A同步到DataServer B,其中2的数据已经迁移完成,3的数据正在迁移,4的数据还没迁移。在迁移完成前,客户端仍访问原始路由表,即访问DataServer A:当访问2中的数据时,则A会将该请求转发给B,并且将B的返回结果返回给客户端;如果是访问3中的数据,当作修改操作时,A会记录修改的log,当3迁移完成时,A会把log发送给B,在B上根据log更新3的数据,当两者数据完全一致时,3的数据迁移才算完成;当访问4时,则正常访问A即可。

当因为某台dataserver宕机导致的数据迁移时,客户端会收到ConfigServer发送过来的中间临时状态的路由表,表中会把宕机的DataServer所负责的bucket临时指派给具有其备份副本的DataServer来处理,此时,服务保持可用,但负载可能不均衡,当迁移完成后,才能重新达到一个新的负载均衡的状态

6.4 系统可扩展性

数据自动迁移:当有新节点加入或者有节点不可用时,数据节点会根据Configserver新生成的路由表,自动将在新表中不由自己负责的数据迁移到新的目标主节点中。迁移完成后,客户端可以从 configserver 同步到新的对照表,完成扩容或者容灾过程,具体的迁移过程如下:

ConfigServer维护hash_table【原始路由表】,m_hash_table【中间状态路由表】,d_hash_table【最终路由表】三张表,DataServer通过心跳获取到hash_table和d_hash_table,根据hash_table和d_hash_table的差异构建迁移任务,并按照d_hash_table进行数据迁移,每迁移完成一个桶,DataServer就会向ConfigServer更新状态,更新m_hash_table,当m_hash_table和d_hash_table完全一致,表示迁移完成

7. 热点数据处理

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

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

7.1 DataServer上的热点统计过程

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

7.2 读热点方案

服务端设计

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

本方案通过在DataServer上划分一块HotZone存储区域的方式来解决热点数据的访问。该区域存储当前产生的所有读热点的数据,由客户端配置的缓存访问逻辑来处理各级缓存的访问。多级缓存架构如下:
在这里插入图片描述
所有DataServer的HotZone存储区域之间没有权重关系,每个HotZone都存储相同的读热点数据。客户端对热点数据Key的请求会随机到任意一台DataServer的HotZone区域,这样单点的热点请求就被散列到多个节点乃至整个集群。

客户端设计

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

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

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

7.3 写热点方案

服务端设计

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

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

客户端设计

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

8. Java中使用的基本步骤

导入Tair客户端库
根据您所使用的Tair版本和具体的客户端库,将相应的依赖项添加到您的Java项目中。例如,如果您使用的是Tair的Java客户端库,可以在Maven或Gradle配置文件中添加相应的依赖项。

创建Tair客户端实例
使用Tair客户端库提供的类和方法,创建Tair客户端实例。通常,您需要指定Tair集群的地址、端口和其他配置信息。例如:

TairManager tairManager = new DefaultTairManager();
tairManager.setConfigServerList("127.0.0.1:5180");
tairManager.init();

执行数据操作
通过Tair客户端实例,您可以执行各种数据操作,如存储键值对、获取键值对、删除键值对等。以下是一些常见的示例:

存储键值对

boolean success = tairManager.put(0, “myKey”, “myValue”);
获取键值对
String value = tairManager.get(0, “myKey”);
删除键值对
boolean success = tairManager.delete(0, “myKey”);
错误处理和异常处理
在与Tair交互的过程中,可能会出现网络故障、请求超时或其他错误。您可以使用try-catch语句捕获和处理异常,以确保代码的稳定性。例如:

try {
    String value = tairManager.get(0, "myKey");
    // 处理获取到的值
} catch (TairException e) {
    // 处理Tair异常
} catch (Exception e) {
    // 处理其他异常
}

关闭Tair客户端
在您的程序结束时,记得关闭Tair客户端,释放资源。例如:

tairManager.close();

  • 12
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值