简介

tair 是淘宝自己开发的一个分布式 key/value 存储引擎. tair 分为持久化和非持久化两种使用方式. 非持久化的 tair 可以看成是一个分布式缓存. 持久化的 tair 将数据存放于磁盘中. 为了解决磁盘损坏导致数据丢失, tair 可以配置数据的备份数目, tair 自动将一份数据的不同备份放到不同的主机上, 当有主机发生异常, 无法正常提供服务的时候, 其于的备份会继续提供服务.

tair 的总体结构

tair 作为一个分布式系统, 是由一个中心控制节点和一系列的服务节点组成. 我们称中心控制节点为config server. 服务节点是data server. config server 负责管理所有的data server, 维护data server的状态信息. data server 对外提供各种数据服务, 并以心跳的形式将自身状况汇报给config server. config server是控制点, 而且是单点, 目前采用一主一备的形式来保证其可靠性. 所有的 data server 地位都是等价的.

tair 的负载均衡算法是什么

tair 的分布采用的是一致性哈希算法, 对于所有的key, 分到Q个桶中, 桶是负载均衡和数据迁移的基本单位. config server 根据一定的策略把每个桶指派到不同的data server上. 因为数据按照key做hash算法, 所以可以认为每个桶中的数据基本是平衡的. 保证了桶分布的均衡性, 就保证了数据分布的均衡性.

增加或者减少data server的时候会发生什么

当有某台data server故障不可用的时候, config server会发现这个情况, config server负责重新计算一张新的桶在data server上的分布表, 将原来由故障机器服务的桶的访问重新指派到其它的data server中. 这个时候, 可能会发生数据的迁移. 比如原来由data server A负责的桶, 在新表中需要由 B负责. 而B上并没有该桶的数据, 那么就将数据迁移到B上来. 同时config server会发现哪些桶的备份数目减少了, 然后根据负载情况在负载较低的data server上增加这些桶的备份. 当系统增加data server的时候, config server根据负载, 协调data server将他们控制的部分桶迁移到新的data server上. 迁移完成后调整路由. 当然, 系统中可能出现减少了某些data server 同时增加另外的一些data server. 处理原理同上. 每次路由的变更, config server都会将新的配置信息推给data server. 在客户端访问data server的时候, 会发送客户端缓存的路由表的版本号. 如果data server发现客户端的版本号过旧, 则会通知客户端去config server取一次新的路由表. 如果客户端访问某台data server 发生了不可达的情况(该 data server可能宕机了), 客户端会主动去config server取新的路由表.

发生迁移的时候data server如何对外提供服务

当迁移发生的时候, 我们举个例子, 假设data server A 要把 桶 3,4,5 迁移给data server B. 因为迁移完成前, 客户端的路由表没有变化, 客户端对 3, 4, 5 的访问请求都会路由到A. 现在假设 3还没迁移, 4 正在迁移中, 5已经迁移完成. 那么如果是对3的访问, 则没什么特别, 跟以前一样. 如果是对5的访问, 则A会把该请求转发给B,并且将B的返回结果返回给客户, 如果是对4的访问, 在A处理, 同时如果是对4的修改操作, 会记录修改log.当桶4迁移完成的时候, 还要把log发送到B, 在B上应用这些log. 最终A B上对于桶4来说, 数据完全一致才是真正的迁移完成. 当然, 如果是因为某data server宕机而引发的迁移, 客户端会收到一张中间临时状态的分配表. 这张表中, 把宕机的data server所负责的桶临时指派给有其备份data server来处理. 这个时候, 服务是可用的, 但是负载可能不均衡. 当迁移完成之后, 才能重新达到一个新的负载均衡的状态.

桶在data server上分布时候的策略

程序提供了两种生成分配表的策略, 一种叫做负载均衡优先, 一种叫做位置安全优先: 我们先看负载优先策略. 当采用负载优先策略的时候, config server会尽量的把桶均匀的分布到各个data server上. 所谓尽量是指在不违背下面的原则的条件下尽量负载均衡. 1 每个桶必须有COPY_COUNT份数据 2 一个桶的各份数据不能在同一台主机上; 位置安全优先原则是说, 在不违背上面两个原则的条件下, 还要满足位置安全条件, 然后再考虑负载均衡. 位置信息的获取是通过 _pos_mask(参见安装部署文档中关于配置项的解释) 计算得到. 一般我们通过控制 _pos_mask 来使得不同的机房具有不同的位置信息. 那么在位置安全优先的时候, 必须被满足的条件要增加一条, 一个桶的各份数据不能都位于相同的一个位置(不在同一个机房). 这里有一个问题, 假如只有两个机房, 机房1中有100台data server, 机房2中只有1台data server. 这个时候, 机房2中data server的压力必然会非常大. 于是这里产生了一个控制参数 _build_diff_ratio(参见安装部署文档). 当机房差异比率大于这个配置值时, config server也不再build新表. 机房差异比率是如何计出来的呢? 首先找到机器最多的机房, 不妨设使RA, data server数量是SA. 那么其余的data server的数量记做SB. 则机房差异比率=|SA – SB|/SA. 因为一般我们线上系统配置的COPY_COUNT是3. 在这个情况下, 不妨设只有两个机房RA和RB, 那么两个机房什么样的data server数量是均衡的范围呢? 当差异比率小于 0.5的时候是可以做到各台data server负载都完全均衡的.这里有一点要注意, 假设RA机房有机器6台,RB有机器3台. 那么差异比率 = 6 – 3 / 6 = 0.5. 这个时候如果进行扩容, 在机房A增加一台data server, 扩容后的差异比率 = 7 – 3 / 7 = 0.57. 也就是说, 只在机器数多的机房增加data server会扩大差异比率. 如果我们的_build_diff_ratio配置值是0.5. 那么进行这种扩容后, config server会拒绝再继续build新表.

tair 的一致性和可靠性问题

分布式系统中的可靠性和一致性是无法同时保证的, 因为我们必须允许网络错误的发生. tair 采用复制技术来提高可靠性, 并且为了提高效率做了一些优化, 事实上在没有错误发生的时候, tair 提供的是一种强一致性. 但是在有data server发生故障的时候, 客户有可能在一定时间窗口内读不到最新的数据. 甚至发生最新数据丢失的情况.

tair提供的客户端

tair 的server端是C++写的, 因为server和客户端之间使用socket通信, 理论上只要可以实现socket操作的语言都可以直接实现成tair客户端. 目前实际提供的客户端有java 和 C++. 客户端只需要知道config server的位置信息就可以享受tair集群提供的服务了.

主要的性能数据

  待补充

一. 修改配置

leveldb中有一系列参数会与读写的效率有关,将相关的配置以及编译常量统一修改成可运行时配置参数,测试选取最佳配置值。

二. 实例个数控制

首先确定在一个tair server上要启几个leveldb实例?
Tair中以桶来组织数据,如果按照一个桶一个leveldb实例,在做迁移复制的时候会很方便,但考虑如果在一块磁盘上起多个实例,那么整体看来,多个顺序写变成了随机写,每个实例的compact进程会加剧整个磁盘的随机IO,所以并不采用每个桶一个实例,而是针对磁盘的数量由相关配置控制实例的个数。

三. 内部key的格式

为实现Tair中的功能逻辑,ldb传入leveldb的user-key格式如下:

1)    Tair中的数据可以设置过期时间,过期时间保存可以保存在在value的meta中,但考虑能在leveldb内部提前检查,省去解析value的消耗,将过期时间保存在key中,但并不参与排序。
2)    Tair中的数据组织以及迁移复制都是以桶(bucket)单位,为获得一个桶的数据,添加桶号前缀,保证一个桶的数据都存储在一起。leveldb内部对key做前缀压缩,桶号基本都可以被压缩掉。
3)    Tair中的数据区分namespace,会将namespace作为客户端传入key的前缀存储。

四. 自定义comparator

为了实现Tair中的功能逻辑,实现自定义的comparator传入leveldb,实现自定义的排序逻辑(传入leveldb的user-key中表示过期时间的前四个字节不参与排序),并为comparator添加两个判断数据是否有效的逻辑接口(ShouldDrop()/ShouldDropMaybe()),修改leveldb内部做遍历以及compact时判断数据是否有效(kTypeValue/kTypeDeletion)的逻辑。
1)    ShouldDropMaybe(): 用来判断数据是否已经过期。解析key中的expired_time即可。
2)    ShouldDrop(): 用来判断数据是否属于已经清理掉的数据(bucket已经迁移或者namespace已经被清理)。
3)    区分过期数据与清理数据的判断,是因为丢弃过期数据必须保证该key是数据的最后出现,否则删除该数据会让该key失去最后的更新状态,而清理数据有gc信息保证,不需要关心数据的状态。

五. 清理数据/自定义的内部compact逻辑

这里把清理数据的操作称为gc。
1.    迁移的bucket以及清理的namespace中的数据
一旦发生bucket迁移或者清理namespace,会把相应的信息保存下来(GcNode)

 struct GcNode{// 迁移走的bucket或者清掉的namespaceint32_t key_;// 清理发生时的SequnceNumber,用来判断数据的时间点uint64_t sequence_;// 清理发生时的FileNumber,用来缩小compact的范围uint64_t file_number_;// 清理发生时的时间uint32_t when_;};

1)    Tair中会有桶迁移或者namespace清理的操作,废弃的数据并不会立刻清理,依靠后续的compact进程清理。但同时桶又可能被迁移回来,namespace也可能继续使用。leveldb中的SequnceNumber恰好可以标识数据的时间点,所以在做数据清理的时候,记录下当时的SequnceNumber(sequnce_),在做判断的时候,只有小于sequnce_的数据才认为可以被丢弃。
2)    filenumber_是为了缩小主动compact的范围。
leveldb自身进行compact的过程中,加入自实现comparator的ShouldDropMaybe()/ShouldDrop()判断逻辑,会将对应的gc数据清理。但leveldb自身的compact进程并不能保证将所有的数据清理掉,所以添加compact的定时线程,主动触发compact做数据清理。对于清理的bucket或者namespace,根据key的格式,可以构造出需要compact的key-range,但直接使用leveldb提供的CompactRange有以下问题:
1)    如果某个sstable在记录gc之后已经被compact过,所要清理的数据就已经丢弃掉了,并不需要再做compact。
2)    主动触发的compact并不是基于均衡db状态,所以造成的level迁移可能会有反作用。
对于1)2)的问题,做以下策略:
1)    FileNumber全局递增可以用来标识时间点,gc时,记录下当时的FileNumber,主动compact时,只需要选取符合key-range并且FileNumber小于记录的filenumber_的sstable即可,缩小需要compact的sstable范围。
2)    主动触发的compact只选取level-n中的sstable,compact后,也只生成level-n中的sstable,level之间的均衡,仍由内部compact进程负责。
3)    基于上述1) 2),为leveldb添加CompactRangeSelfLevel()逻辑,实现1) 2)中的策略,主动触发compact以清理数据,整个db的均衡仍由内部的机制保证。
gc信息会同时记binlog,在server重启时replay。

2.    过期的数据
因为过期是一个持续的时间状态,如果要完全回收过期的数据,只能对全db做compact,这样做的性能比不合算,所以目前对过期数据不做特别的主动清理,依靠内部以及外部触发的compact进程中回收空间。

六. 上层cache

leveldb内部有sstable元信息和block数据的cache,优化读的效率,在leveldb上层再嵌入Tair自带的mdb做KV层面的cache,并添加cache的信息统计。当前统计看到,热点数据的读基本落在mdb中。

七. 后续的优化

1)    leveldb本身的一些优化(参见leveldb的实现解析)。
2)    优化网络的使用,使用新的网络框架。
3)    ssd使用优化。leveldb内部做的一些细节优化针对于sas盘的IO性能,当前使用的ssd IO能也未充分利用。后续针对提升ssd使用性能做相应的IO优化(dio)。
4)     内存的优化使用。大内存的使用有很大的优化余地,避免swap的使用,pagecache的相应回写策略配置。
5)    对不存在数据查找的优化,采用mock value处理或者添加bloomilter。
6)    range 以及数据dump功能的实现。

欢迎大家对leveldb的使用优化提出宝贵建议。

广告时间: Tair现在已经将Redis的存储部分抽离出来,作为非持久化的存储引擎rdb,即将上线使用,欢迎大家强势围观。

Tair ldb(leveldb存储引擎)实现介绍相关推荐

  1. Tair存储引擎简单介绍以及常见API操作

    一.Tair存储引擎 Tair的存储引擎有一个抽象层(storage_manager),只要实现存储引擎接口,便可以替换Tair的底层存储引擎. 可插拔存储引擎-类似MySQL Tair默认包含四种存 ...

  2. mysql InnoDB存储引擎的介绍

    mysql InnoDB存储引擎的介绍 概念 1.InnoDB是MySQL默认的存储引擎,如果需要其不支持的特性,则考虑使用其他存储发动机. 2.InnoDB采用MVCC支持高并发,实现四个标准隔离级 ...

  3. 基于淘宝开源Tair分布式KV存储引擎的整合部署

    一.前言 Tair支撑了淘宝几乎所有系统的缓存信息(Tair = Taobao Pair,Pair即Key-Value键值对),内置了三个存储引擎:mdb(默认,类似于Memcache).rdb(类似 ...

  4. MySQL存储引擎的介绍

    数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建.查询.更新和删除数据操作.不同的存储引擎提供不同的存储机制.索引技巧.锁定水平等功能,使用不同的存储引擎还可以获得特定的功能. ...

  5. BitCask 持久化hash存储引擎 原理介绍

    文章目录 前言 引擎背景 引擎原理 1. 磁盘数据结构 2. 内存数据结构 3. 读流程 4. 数据合并 总结 前言 最近工作中部分项目中,对存储引擎的需求希望高性能的写.点查,并不需要Range.这 ...

  6. innodb和my查询速度_吃透MySQL:MyISAM和InnoDB存储引擎详细介绍

    一,MySQL基本架构 MySQL基础架构可以分为两大类:Server层和存储引擎层. Server层: Server层涵盖了MySQL大部分核心业务功能,并且所有存储引擎的功能都在这一层实现. 存储 ...

  7. MySQL存储引擎InnoDB、MyISAM和MEMORY介绍详解和区别

    文章目录 MySQL存储引擎InnoDB.MyISAM和MEMORY介绍详解和区别 InnoDB存储引擎 特点 操作示例 创建InnoDB表 修改表引擎为InnoDB MyISAM存储引擎 特点 操作 ...

  8. MySQL 数据库存储引擎介绍

    文章目录 一.存储引擎概念介绍 二.MyISAM 存储引擎 1. MyISAM 简介 2. MyISAM 表支持 3 种不同的存储格式 (1) 静态(固定长度)表 (2) 动态表 (3) 压缩表 3. ...

  9. mysql的存储引擎详解_Mysql存储引擎详解

    存储引擎的介绍 关系型数据库表是用来存储和组织信息的数据结构,可以将表理解为由行和列组成的表格. 由于表的类型不同,我们在实际开发过程中,就有可能需要各种各样的表,不同的表就意味着存储不同类型的数据, ...

最新文章

  1. python安装步骤电脑版-超详细的小白python3.X安装教程|Python安装
  2. 【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )
  3. 使用SQLALCHEMY 出现warning的问题解决
  4. Gradle 1.12用户指南翻译——第五十四章. 构建原生二进制文件
  5. 存储ic载板_延伸IC领域 崇达技术拟将持有普诺威55%股权
  6. modem (1)---手机主叫的信道流程与Modem Log简单分析
  7. HttpClient短信接口
  8. 【洛谷P4219】【BJOI2014】—大融合(线段树合并)
  9. tensorflow.python.framework.errors_impl.NotFoundError: Failed to create a directory: ../user_data\co
  10. Isight 软件集成AVLCruise软件方法探讨
  11. mmsegmentation自定义数据集
  12. 支付宝生活号开发中所遇到的困难及解决记录
  13. RK3588 调试 phy
  14. Xmanager7 解决图形显示问题
  15. NEO从源码分析看数字资产
  16. SpringBoot整合TICK(Telegraf+InfluxDB+Chronograf +Kapacitor)监控系列之一:InfluxDB
  17. 聚观早报 | 多款热门游戏停服一天;比亚迪下月在日本开售
  18. 【数据可视化应用】xarray 绘图可视化(五)-二进制GrADS气象数据处理(附代码)
  19. C语言程序设计(第二版) 主编:余贞侠 何钰娟 课后习题 代码题答案
  20. 兄弟连社团——全国最大的PHP技术社团

热门文章

  1. UE4材质(二):PBR材质
  2. 中英文切换时英文的样式乱了怎么处理
  3. 轻松入门Android直播相关技术 从0搭建直播系统
  4. cache stm32h7_STM32H7的Cache和MPU
  5. 教你如何写出完美的论文——5. 做笔记
  6. java华氏温度与摄氏度的互相转换
  7. 大数据面试常见问题(三)——Hadoop部分
  8. 图片文件太大?缩小图片文件的2个小技巧
  9. 2017年北京邮电大学计算机考研机试试题及答案
  10. 将日/分钟数据转为周线、月线或其他周期