什么是OTS
OTS 是Open Table Service的简称,现在已更名为表格存储Table Store,官网对它的解释为:OTS是构建在阿里云飞天分布式系统之上的 NoSQL 数据库服务,提供海量结构化数据的存储和实时访问。OTS 以实例和表的形式组织数据,通过数据分片和负载均衡技术,达到规模的无缝扩展。OTS 向应用程序屏蔽底层硬件平台的故障和错误,能自动从各类错误中快速恢复,提供非常高的服务可用性。OTS 管理的数据全部存储在 SSD 中并具有多个备份,提供了快速的访问性能和极高的数据可靠性。用户在使用 OTS 服务时,只需要按照预留和使用的资源进行付费,无需关心数据库的软硬件升级维护、集群缩容扩容等复杂问题。
上面的介绍我们可以简单的概括为:OTS是一个NoSQL的数据库(你可以将它类比为HBase),在使用方面我们可以将OTS类比为一个技术黑箱,它已经为我们把存储扩容、数据备份、负载均衡等工作做了,使用过程中我们只需透明的使用其提供的高可用和高并发的特性即可。
OTS和传统数据关系型数据库的区别
估计很多人看了上面的介绍加上对上面提到的HBase不是很了解,现在对于OTS还是有很多疑问。没关系,接下来将它和传统关系型数据库Mysql、SQLServer等做一个比较,或许这下你就能更加清晰的认识OTS了。
OTS的数据模型也是以二维表为中心的,表有行和列的概念,但是与传统数据库不一样,OTS的表是稀疏的,稀疏指的是它的每一行可以有不同的列,可以动态增加或者减少属性列,建表时不需要为表的属性列定义严格的schema。相对于传统数据库的丰富功能(视图、索引、事务、丰富的SQL语句支持),OTS提供较为基础的功能,但是具有更好的规模扩展性,能够较容易的支持更大的数据规模(百TB级别)和并发访问(单表10万QPS)。在编程方面,OTS提供统一的HTTP Restful API,不支持传统的SQL语句标准。
OTS的特点
对OTS做了初步的了解后,那么问题来了,它有什么特性,在存储产品如此丰富的现状下我们有什么理由去选用它呢?
它的主要特性我们可以大致概括为以下几个方面:
- 扩展性
- 动态调整预留读写吞吐量
应用在创建表的时候,需要根据业务访问的情况来配置预留读写吞吐量。OTS 根据表
的预留读写吞吐量进行资源的调度和预留,从而保证应用获得可预期的性能。在使用
过程中,应用还可以根据应用的情况动态修改预留读写吞吐量。 - 无限容量
OTS 表的数据量没有上限,随着表数据量的不断增大,OTS 会进行数据分区的调整
从而为该表配置更多的存储。
- 数据可靠性
- OTS 通过存储多个数据备份及备份失效时的快速恢复,提供极高的数据可靠性。
- 高可用性
- 通过自动的故障检测和数据迁移,OTS 对应用屏蔽了机器和网络的硬件故障,提供高可用
性。
- 管理便捷
- 应用程序无需关心数据分区的管理,软硬件升级,配置更新,集群扩容等繁琐运维任务。
- 灵活的数据模型
- OTS 的表无固定格式要求,每行的列数可以不相同,支持多种数据类型 (Integer、Boolean、
Double、String、Binary)。
- 监控集成
- 用户可以从 OTS 控制台实时获取每秒请求数、平均响应延时等监控信息。
这些概括性的对OTS的特点进行了描述,具体量化的服务提供标准如可用率等可以参见官网:
表格存储(Table Store)服务等级协议
这里可以给大家提供几个主要数据,供大家参考:
- 单表百TB级别数据规模,十万级别QPS。(传统单机数据库的100倍)
- 10毫秒级别单行读写延迟
- 分钟级别单机故障恢复时间
OTS数据模型
OTS 数据模型概念包括表、行、主键和属性。
表是行的集合,行由主键和属性组成。主键列和属性列均由名称和值组成。表中的所有行都必须包含相同数目和名称的主键列,但每行包含的属性列的数目可以不固定,名字和数据类型也可以不同。
与主键列不同,每个属性列可以包含多个版本,每个版本号(时间戳)对应一个列值。
对于接触过数据库的人来说,理解上面的模型不是很困难,同样也有主键和属性列之分,但需要我们注意的是复合主键最多只能包含4列,此外让我们疑惑的是模型里面出现了分区键(partition key)这个概念,这又是干什么的?
分区键(Partition Key)
还记得我们在说OTS特点的时候第一个就提到了它的扩展性,对于OTS来说扩展性是它很大的一个亮点,而要实现它的扩展性,与分区键的关系密不可分。
在OTS存储中,一张大表会被自动的切分成很多个数据分区(也叫partition),这些partitions被尽量均匀的调度到不同的存储节点上进行数据的存储和请求的处理。当一个partition的数据规模增长到一定大小或者这个partition上的请求过热,可以对这个partition进行分裂,分裂成数据规模更小的两个partition,也对落到原先这个partition上的请求进行了分摊。分裂之后的partition会被迁移到不同的存储节点上,从而减小原始节点上的访问压力。当机器资源不足进行扩容时,也可以触发partition的迁移从而达到数据和访问压力的均衡。通过partition的切分、分裂和迁移等机制,OTS支持数据和访问规模的动态伸缩。
一般情况下,我们将组成主键的第一个主键列作为分区键, 具有相同分区键的行属于同一个分片,一个分片可能包含多个分片键。分片的过程是自动进行的,无需用户进行干涉。
我们需要牢记的是,分区键对于OTS来说是一个很重要的因素,我们在设计表结构的时候一定要根据应用需求设计出一个合理的分区键,设计的一些准则和建议可以参考这篇文章——OTS最佳实践——设计良好的主键
列值类型
OTS一共支持五种类型的列值String、Integer、Double、Boolean、Binary。每种类型有如下限制:
类型 | 值 | 能否作为主键 | 空间占用限制 |
---|---|---|---|
String | UTF-8 字符串,可以为空字符串 | 是 | 不超过 64KB,如果为主键列不超过1KB |
Integer | 范围为 -2ˆ63 ~ 2ˆ63-1 的 64 位整型 | 是 | 固定 8Byte |
Double | 范围为 -10ˆ308 ~ 10ˆ308 的双精度浮点数 | 否 | 固定 8Byte |
Boolean | 值为 True 或 False | 否 | 固定 1Byte |
Binary | 二进制数据,可以为空 | 否 | 不超过64KB |
OTS支持的操作
表操作
- ListTable -- 列出实例下的所有表
- CreateTable -- 创建表
- DeleteTable -- 删除表
- DescribeTable -- 获取表的属性信息
- UpdateTable -- 更新表的预留读写吞吐量配置
数据操作
- 单行操作
- GetRow -- 读取单行数据
- PutRow -- 新插入一行。如果该行内容已经存在,先删除旧行,再写入新行
- UpdateRow -- 更新一行。应用可以增加、删除一行中的属性列,或者更新已经存在的
属性列的值。如果该行不存在,那么新增一行 - DeleteRow -- 删除一行
- 批量操作
- BatchGetRow -- 批量读取一张或者多张表的多行数据
- BatchWriteRow -- 批量插入、更新、删除一张表或者多张表的多行数据
- 范围读取
- GetRange -- 读取表中一个范围内的数据
操作说明
在OTS中开发者是通过统一的HTTP Restful API来完成上述操作的。详细的操作说明,和数据的格式请参考官网文档:API操作概览
OTS典型应用场景
看到这里我们对于OTS已经有了一个大致的了解,它有很多特别的优点,但任何一款产品并不是万能的,并不能适用于所有的领域。下面我们来看看根据OTS的这些特性,它针对那些应用场景特别适用:
移动社交
使用OTS来存储人与人之间产生的大量社交信息,包括聊天、评论、跟帖和点赞,OTS的弹性资源按量付费能够以较低的成本满足访问波动明显大并发低延时的需要。
金融风控
低延时、高并发,弹性资源可以让的风控系统永远工作在最佳状态,牢牢控制交易风险,灵活的数据结构能够让业务模式跟随市场需求快速迭代。
电商物流
大量的交易订单及物流跟踪信息,使用OTS能够让使用者无需担心数据规模,它的弹性资源,可以从容应对节日促销活动。
云存储解决方案
大量的联系人、短信、通话记录、便笺等结构化信息与图片、视频、文件的元数据正好与OTS数据模型相对应,并且OTS的备份机制可以保障这些数据的安全性。
日志监控
我们可以将应用程序的监控和日志信息写入OTS,提供在线的日志检索,并利用离线数据处理服务ODPS进行监控与日志分析,挖掘其中的数据价值。
目前阿里内部采用OTS的产品有:
- 云OS云空间
- 钉钉即时聊天、用户关系和行为跟踪数据
- 冰火鸟TCIF
- ODPS meta存储
实例说明
我们通过一个例子来应用下上面的知识点,加深对OTS的理解吧。
手机云空间
我们就拿OTS典型的手机云空间这个例子来做说明:
应用需求
- 存储手机用户的联系人、通话记录、短信、便签
- 目标是上千万的手机用户,每个用户数据永久保留,数据规模未来可达几百TB
基于OTS的解决方案
- 不同的业务数据放在不同的数据表中,属于一个表组,以userid为partition key进行数据分区
- 每张业务表都附带多张视图,满足不同顺序的数据查询需求
- 表组中还有一张用户数据统计表,对其他表的操作同时对该表的记录内容进行更新,确保数据的一致性
表结构设计模型
用户表
用户ID | 短信数目 | 联系人数目 | 总容量 |
---|---|---|---|
U0001 | 2000 | 200 | 100,000,00 |
U0002 | 1024 | 500 | 100,000,00 |
... | ... | ... | ... |
短信表
用户ID | 接收时间 | 唯一ID | 对方号码 | 短信内容 | 短信类型 |
---|---|---|---|---|---|
U0001 | 2016-08-09 | 0001 | 123456 | hello | 接收 |
U0002 | 2016-08-09 | 0002 | 123445 | hi | 发送 |
... | ... | ... | ... | ... | ... |
。。。
用户其他信息的表格设计类似于短信表。我们可以看到对于这些不同的表,我们可以将用户ID作为其 分区键 这样同一用户的所有信息都会存储在同一数据分区下,读写遍历的同时,也可以支持对同一用户不同表数据的事务操作。
文章为了让大家快速认识OTS有些细节东西没有讲,例如这里提到的事务操作,在OTS中同样可以支持事务的提交和回滚操作,事务可以应用在同一个表中,也可以应用在同一分区下的表格中。对于这些细节部分大家可以看官文的帮助文档进行学习:OTS官方帮助文档
接着我们的分析,我们短信表中有个唯一ID这个属性列,这个列起到的作用是防止主键重复,我们知道在所有的数据库中主键可用于唯一区分数据库不同的行不能重复,但有些情况下当我们用几个属性列设置了复合主键后依然会有重复的可能例如这里的短信表,这时候我们就可以引如一个没有实际意义的属性列作为复合主键中的唯一区分不同行的变量因素,这就是唯一ID属性段的作用。
其他的一些分析不是很难,大家按照自己的理解即可。可以看到当我们熟悉关系型数据库的使用后,理解和使用OTS没有多大的障碍。