HTAP数据库背景及现状
起源
大型实时分析应用的逐渐流行(实时库存/定价、欺诈检测,风险分析,物联网等);这些系统需要一个分布式的数据管理系统,要求能处理高并发的TP请求,同时对近期的数据进行分析;有些应用甚至会在TP请求中进行AP操作;Gartner:即有事务又分析的系统叫HTAP;实时分析:指的是实时交易过程中的分析需求,不是数据时效性上的实时。
方案1:一套系统同时OLTP和OLAP
传统的DBMS可以在一套系统上TP和AP,但对这两种业务场景都不高效;基于内存的行存( VoltDB, Hekaton, MemSQL, Silo)和列存( MonetDB , Vertica , BLU , SAP HANA)系统,这些系统开始只是为一个场景专门设计的,后来为了HTAP增量了另一场景的。
- 底层数据分开存储
SAP HANA 和 Oracle’s TimesTen 最初是为OLAP专门设计的,同时也ACID事务操作;不过事务的数据是以行存方式的,而分析操作是通过列存的;MemSQL最初是为in-memory OLTP设计的,后来也分析。对于TP数据是以行存方式存在内存中的,当数据需要写到磁盘中时,会转换成列存;IBM dashDB也是从传统的行存向HTAP演进的系统。通过行列混合的方式来分别TP和AP;HyPer是从一开始就为HTAP设计的,最初使用行存来同时TP和AP,不过现在也通过列存方式来更好的AP场景。
- 底层用一种方式存储数据
H2TAP,学术项目,以行存的方式同时TP和AP;Hive,SQL-on-hadoop的解决方案之一,AP系统,在0.13版本开始通过ORCFile事务,但主要的应用场景是维度表更新以及实时流数据摄取;Impala + kudu:SQL分析及数据的更新和删除。
这类系统跟传统DBMS面临同样的问题,没办法同时为AP和TP进行优化。对于采用列存的系统,需要通过批量的方式来提高事务的吞吐能力;对于采用行存的系统,无法实现最佳的分析效果。
方案2:两套系统来组合来OLTP和OLAP
- 解耦AP和TP的底层存储
现状
需要用户的应用程序自己来协调AP和TP系统的使用;数据在两个系统之间是通过ETL方式同步的;这类方案在目前的大数据系统中非常常见,通常使用kv系统(如cassandra)来承载TP负载,然后将数据转换成 Parquet or ORC 文件存储到HDFS中,再使用SQL-on-hadoop方案进行数据分析。
- AP和TP共享底层存储
这类系统通常是使用Spark之类的系统,在原有数据上大规模分析的场景。由于数据只有一份,因此AP分析的数据是实时数据。
SAP HANA Vora:TP业务负载有vora直接支撑,而分析场景则通过Spark-SQL来;SnappyData:使用GemFire来承载TP业务,通过Spark生态来AP业务;HBase 和Cassandra等kv系统被广泛应用在需要实时更新的场景,而对这些数据的分析场景在通过组合SQL-on-Hadoop的解决方案来实现。TP和AP系统访问的是同一份数据,这需要开发一些额外的扩展,以使得AP引擎能直接读取TP存储中的数据,比如Spark HBase connector,Spark Cassandra connector等。通过connector来进行AP分析通常非常慢;另外一些SQL-on-hadoop系统,使用HBase作为快速更新的存储引擎,如:HIVE, Impala, IBM Big SQL, and Actian VectorH。数据的处理是通过HBase的处理引擎来实现的;Splice Machine 、 Phoenix则是在HBase之上构建了SQL引擎;基于HBase的AP系统,在处理AP任务时都比较慢,因为在HBase上执行Scan非常慢。HBase适合快速更新和点查的场景;Wildfire:IBM最近开发的一套HTAP系统,使用列存方式来同时AP和TP,使用的是Parquet格式。Wildfire可以立即分析最近提交的更新,同时使用Spark生态来执行大规模并行分析任务,提交给SparkSQL的请求会被尽可能的下沉到Wildfire引擎来进行数据处理。
现状总结
目前没有一个系统true-HTAP; 1. 大多数系统已经分别了AP请求和TP请求的处理,但是没有系统在TP中执行AP的场景;
2.要真正的HTAP,需要在同一个请求中既有TP又有AP的场景。
目前大多数系统需要组合各种解决方案来达到HTAP场景的需求,这对用户部署和维护系统带来挑战;目前大多数TP系统为了加速TP的更新和点查,将索引全部放在了内存中,但是对于更大规模数据的场景,索引全部在内存中会导致TP系统变慢,应当考虑一种仅保留部分索引在内存中的方案,以提高常用数据的访问性能;为AP场景设计的存储引擎,通常使用对象存储或者共享文件系统来存储数据。这些存储格式主要是为scan场景进行优化,无法提供高效的点查和更新能力。目前这还是一个未解决的难题。
设计HTAP系统要做的一些决策
Query processing and ingestion engines(数据分析和数据摄取引擎)Storage options (存储方式:一套存储还是混合存储)Data organization (数据组织格式:行存还是列存)Transactional semantics (事务语义)Recency of data being read by OLAPIndexing support(索引)
HTAP类数据库分析
TiDB
TiSpark
所属分类
两套系统来组合来OLTP和OLAP(采用Spark生态)AP和TP共享底层存储TiSpark 是将 Spark SQL 直接运行在 TiDB 存储引擎 TiKV 上的 OLAP 解决方案
TiSpark 深度整合了 Spark Catalyst 引擎, 可以对计算提供精确的控制,使 Spark 能够高效的读取 TiKV 中的数据,提供索引以实现高速的点查通过多种计算下推减少 Spark SQL 需要处理的数据大小,以加速查询;利用 TiDB 的内建的统计信息选择更优的查询计划
TiFlash
所属分类
底层数据分开存储,TP采用行存,AP采用列存 > AP存储在一定程度上属于TP的一个副本,在比较高的层面上来看,可以认为是一套存储同时行列
两套系统来组合来OLTP和OLAP,TP通过原生的TiDB来SQL和事务;AP则通过TiFlash(基于clickhouse开发的向量化分析引擎)来实现 > 通过动态的SQL路由,TiDB在更高的层面隐藏了AP和TP引擎
技术实现
TiFlash 基于列存和向量化分析引擎(Clickhouse)实现;TiFlash 作为 TiDB 的另外一个存储层,通过raft learner从TiDB 复制数据,并保证数据的事务性;TiFlash目前不SQL直接写数据,因此其角色目前不能成为leader或者follower;TiFlash节点如果发生故障,需要从TP集群重新同步数据;TiFlash作为TiDB的扩展,属于TiDB集群的一部分;通过全局时间戳来保证用户从TiFlash中读到的是最新的数据;通过LSM-Tree来解决列存的更新带来的写放大问题;同时利用其局部有序性来解决AP场景对scan的需求;可以通过动态增减不同类型的节点来增减,TP或AP能力;TP节点和AP节点在系统层面有不同的标签,当启发式算法任务用户下发的SQL是一个AP运算时,会将请求路由到AP节点上执行。在一定程度上隐藏了AP和TP的具体角色分配;一条join语句的两部分数,一份数据需要全表扫描、另一份可以利用索引,则可以分别将这两个子查询调度到不同类型的节点上执行,一部分利用TiFlash的scan能力、一部分利用TiKV的点查能力。
后续计划
SQL直接更新TiFlash中的数据TiFlashMPP,从而可以将TiDB或TiSpark的一部分计算下推到TiFlash执行重新设计TiFlash的存储引擎,从而将性能提升2倍(目前TiSpark+TiFlash的性能,与Spark+Parquet的性能差不多)
TiKV
对应yugabyte的TabletServer(即DocDB),定位和实现框架几乎差别不大,都是在实现一个事务的分布式kv。TiKV是一个单独的项目,更解耦(意味着性能要差)。
都是提供RPC接口都是Raft都是基于rocksdb
MemSQL
技术细节
所属分类
一套系统同时OLTP和OLAP底层数据分开存储技术实现
completely in-memory rowstore(行存,全部在内存中,为TP/HTAP服务,主要针对实时场景)disk-backed columnstore(数据写到磁盘时,改成列存,为AP以及需要查询大量历史数据的HTAP应用服务)一条查询语句可以同时查询内存和磁盘中的数据也内存无法承载情况下的OLTP任务(使用hash indexes)主从复制模式,同步和异步。同步会导致写延迟变高,异步复制则从节点数据落后一段时间没看到如何实现列数据的更新的(MemSQL开启了列存的表不适合频繁更新的场景)MVCC + lock free 充分发挥内存的性能 1. 每当事务修改一行时,MemSQL都会创建一个新版本,该版本位于现有版本之上。该版本仅对进行修改的事务可见。Read查询访问同一行,“查看”该行的旧版本;
2. MemSQL仅在同一行发生写-写冲突的情况下才使用锁;
3. MemSQL为死锁实现了锁等待超时。默认值为60秒;
4.MemSQL将已修改的行排入垃圾收集器。通过避免全表扫描,垃圾收集器可以非常有效地清理旧版本;
5.MemSQL尽可能将单行更新查询优化为简单的原子操作;
skip list 代替btree,以提供更好的扩展性(skip list可以实现lock free访问,更适合纯内存场景)code gen,提高SQL查询性能 1.将SQL编译成C++代码,然后用GCC编译成native code,动态加载到MEMSQL进程。该过程是在SQL首次执行时进行的,并且编译后的代码重启后仍旧有效;
2.编译后的结果会被存储到hash表中,下次如果有相同模式的sql请求,直接使用编译后的代码执行。
CPU效率意味着更高的吞吐量。由于MemSQL每个查询使用较少的指令,因此它们可以实现更高的吞吐量无锁数据结构扩展性好,同时也减少了数据争用期间导致的CPU浪费。MemSQL引擎的每个组件都建立在无锁的数据结构上:链表,队列,堆栈,跳表和哈希表内存数据持久化:定时快照+WAL 1. 事务首先提交到内存缓冲区中,然后异步开始写入磁盘。日志刷新器线程每隔几毫秒将事务刷新到磁盘一次,通过批量提交来提高磁盘IO吞吐;
2. 当日志文件达到已经大小时(2G),会压缩成快照。快照更紧凑、恢复更快;
3. MemSQL完全避免了页面交换,并且可以保证在读/写查询上具有一致的高吞吐量SLA。MemSQL中的任何读取查询都不会等待磁盘。此属性对于对数TB的数据进行实时分析扫描极为重要。
Aggregator:专门的聚合节点,类似Gateway,负责接收用户的查询请求,将请求调度到leaf节点,对查询结果进行聚合,返回最终结果给客户端。根据系统负载,可以配置任意数量的Aggregator节点对于开启了列存的表,数据也会先写到内存中的面向行的skip list中,然后批量往列存中刷;只要数据写到内存skip list中,对客户端就是可见的
特性&定位
从各种数据源(文件、kafka、数据库、S3、HDFS)load数据可以在一条语句中对实时数据和历史数据进行操作Full SQL. MemSQL supports full SQL and transactional semantics.只READ COMMITTED隔离级别冗余和持久化面向高并发、高吞吐、小事务的场景面向需要使用MEMSQL赚钱的场景:因为纯内存架构比较昂贵解决实时需求,能回答当前正在发生什么事情的场景提供实时分析功能,如:min、max、distinct、average不是和BI场景Write-heavy, read-heavy workloads:Machine data、Traffic spikes、Streaming data
HyPer
简介
HyPer最开始是一个学术项目,产出了不少最新的研究成果。目前已经被收购。
其他数据库
kudu
HTAP:放弃事务,只保留TP系统的高性能点查、插入特性;列存:提高OLAP的性能
参考资料
Hybrid Transactional and Analytical Processing - A Survey
https://blog.csdn.net/tidb_pingcap/article/details/76178413
https://blog.csdn.net/TiDB_PingCAP/article/details/100202289
https://docs.memsql.com
http://www.hyper-db.de/
MemFire Cloud是基于MemFireDB云原生和线性扩展能力而打造的数据库云服务,致力于为互联网用户提供一站式数据库自助服务,实现按需使用,随用随取,最大化的节约成本,加速用户的业务创新。