🐘
DOC
BigDataGuide
BigDataGuide
  • 概览
  • bigdata
    • hadoop
      • Hadoop高可用配置
      • HDFS
        • HDFS shell 命令
        • HDFS集群管理
      • MapReduce
        • MapReduce数据操作
        • 分布式处理框架MapReduce
        • MapReduce输入输出剖析
        • MapReduce的工作原理剖析
      • Yarn
        • YARN快速入门
        • Yarn生产配置
    • scheduler
      • Azkaban生产实践
      • 系统架构
    • zookeeper
      • ZookeeperOverView
      • Zookeeper操作与部署
    • cache
      • alluxio
        • AlluxioConfiguration
        • AlluxioDeployment
        • AlluxioOverView
        • AlluxioWithEngine
    • collect
      • canal
        • CanalOverView
      • debezium
        • DebeziumOverView
        • Debezium使用改造
        • Debezium监控系统搭建
      • flume
        • FlumeOverwrite
        • Flume对接Kafka
      • sqoop
        • SqoopOverview
        • Sqoop实战操作
    • datalake
      • hudi
        • Flink基于Apache Hudi+Alluxio的数据湖实践
        • hudiOverview
        • hudiWithFlink
        • hudiWithSpark
        • hudi原理分析
        • hudi数据湖实践
        • hudi调优实践
      • iceberg
        • IcebergWithSpark
        • icebergOverview
        • icebergWithFlink
        • icebergWithHive
    • engine
      • spark
        • SparkOnDeploy
        • SparkOverwrite
        • Spark存储体系
        • Spark计算引擎和Shuffle
        • Spark调优
        • Spark调度系统
        • Spark部署模式
        • 从浅到深剖析Spark源码
        • practice
          • Spark实践
        • spark sql
          • SparkSQL API
        • spark sql
          • SparkSQL优化分析
        • spark streaming
          • SparkStreaming整合Flume
        • 源码分析
          • Spark内存管理
        • 源码分析
          • Spark核心对象
        • 源码分析
          • Spark通信架构
        • 源码分析
          • Spark调度和Shuffle解析
        • 源码分析
          • yarn的部署流程
      • flink
        • connector
          • 自定义TableConnector
        • core
          • Checkpoint机制剖析
          • FlinkOverview
          • 状态处理API
          • TableSQLOverview
        • feature
          • Flink1.12新特性
          • Flink1.13新特性
          • Flink1.14新特性
        • monitor
          • Flink运维监控
          • 搭建Flink任务指标监控系统
        • practice
          • Flink On K8s
          • 记录一次Flink反压问题
        • sourcecode
          • Flink Kafka Connector源码分析
          • FlinkCheckpoint源码分析
          • Blink Planner
          • FlinkTimerService机制分析
          • Flink内核源码分析
          • Flink窗口实现应用原理
          • Flink网络流控及反压
          • Flink运行环境源码解析
          • StreamSource源解析
          • TaskExecutor内存模型原理深入
        • books
          • Flink内核原理与实现
            • 第11-13章Task执行数据交换等
    • graph
      • nebula graph
        • 1.简介
      • nebula graph
        • 2.快速入门
    • kvstore
      • hbase
        • HBaseOverview
        • HBase整合第三方组件
        • Hbase 过滤器详解
      • rocksdb
        • RocksDB On Flink
        • RocksdbOverview
        • Rocksdb组件描述
        • Rocksdb配置
    • mq
      • kafka
        • Kafka Eagle
        • Kafka概念
        • 消费者源码剖析
        • 生产者源码剖析
        • kafka权威指南
          • 1.kafka入门
          • 2.安装Kafka
          • 3.Kafka生产者
          • 4.Kafka消费者
          • 5.深入Kafka
          • 6.可靠的消息传输
          • 7.构建数据管道
          • 8.跨集群数据镜像
          • 9.管理Kafka
        • 深入理解Kafka
          • 深入理解Kafka读书笔记
      • pulsar
        • 1.快速入门
        • 2.原理与实践
    • olap
      • clickhouse
        • ClickHouseOverView
      • druid
        • 概述
      • hive
        • Hive Shell和Beeline命令
        • HiveOverwrite
        • Hive分区表和分桶表
        • hive编程指南
          • 1.基础知识
          • 2.数据类型和文件格式
          • 3.HiveQL相关
          • 4.索引
          • 5.模式设计
          • 7.其他文件格式和压缩方法
          • 8.函数开发
          • 9.文件和记录格式以及Thrift服务
          • 10.存储和安全以及锁
          • 11.HCatalog
      • impala
        • ImpalaOverView
        • Impala Script
        • 使用Impala查询Kudu表
      • kudu
        • KuduConfiguration
        • KuduOverView
        • 表和模式设计
        • Kudu原理分析
        • Kudu生产实践
        • paper
          • KuduPaper阅读
      • kylin
        • 概述
      • presto
        • PrestoOverview
    • tools
      • sqltree
        • calcite
          • 快速入门
  • datawarehouse
    • 数据中台模块设计
      • thoth
      • 数据中台设计
    • 方案实践
      • Kudu数据冷备方案
      • 基于Flink的实时数仓建设
    • 理论
      • 数据仓库概念
      • devops
        • k8s-openshift客户端命令使用
        • maven
          • Maven命令
          • 制作maven骨架
      • 数据中台读书笔记
      • 数据仓库实战
  • base
    • algorithm
      • 算法题解
    • datastructure
      • 数据结构
    • scala
      • Scala基础
    • 分布式理论
      • Raft一致性算法
      • 分布式架构
    • 计算机理论
      • LSM存储模型
    • java
      • 并发编程
        • 并发工具类concurrent
        • 认识并发编程
  • mac os
    • iterm2
      • 多tab操作
  • servicemonitor
    • Prometheus
      • 安装
  • 贡献者指南
由 GitBook 提供支持
在本页
  • 概述
  • 什么是LSM,解决什么问题
  • LSM如何解决问题
  • LSM好处
  • 存储结构
  • 实现方式
  • LSM Paper解读
  • 为什么要有LSM-TREE
  • LSM-Tree大量写优于B-Tree的原因
在GitHub上编辑
  1. base
  2. 计算机理论

LSM存储模型

上一页计算机理论下一页java

最后更新于3年前

概述

什么是LSM,解决什么问题

  • 磁盘的顺序读写速度很快,随机读写很慢。现在市面上7200rpm的希捷SATA硬盘顺序读写基本都能达到300MB/s;但是随机读写却很慢,100 IOPS,假设随机读写每次IO大小为1KB,则随机读写数据带宽为100KB/s;顺序读写和随机读写差了三个数量级。 针对磁盘的上述特性,应用都根据自身读写特点做一些优化。比如数据库的binlog日志就是顺序写入,所以效率很高,但是缺点也比较明显,数据很难查询读取(其实binlog是用来回放恢复数据的,不存在查询读取的使用场景); Mysql的innodb存储引擎底层用B+树数据结构来组织磁盘上的数据,B+树因其节点的度远大于平衡二叉树(平衡二叉树度为2),所以B+树树高很低(3~4),每一次数据的查询只需3~4次磁盘随机IO即可查找到数据(说法不太准确,其实是找到数据所在的page 16K,加载到内存中,再以二分法查找数据,内存二分查找所耗时间远小于磁盘IO,可忽略不计),效率很高;但是insert和update操作是随机的,update隐藏的含义先找到更新的primary-key,更新,调整B+树;查找primary-key的过程很高效,但是调整B+树的磁盘IO开销却很大,因此关系型数据库mysql的写效率一直饱受诟病。那有没有一种替代B+树的数据组织模型,在不太影响读效率的前提下,提高数据的写效率(随机写->顺序写)?

  • 由O'Neil提出的LSM存储模型就是解决上述问题的。

LSM如何解决问题

  • 看下LSM是如何解决上述问题的: 简单来说,就是放弃部分磁盘读性能来换取写的顺序性。 我们假设要写入一个1000个key是随机数的数据,对磁盘来说,最快的写入方式一定是顺序地将每一次写入都直接写入到磁盘中即可。但这样带来的问题是,没办法查询,因为每次查询一个值都需要遍历整个数据才能找到,这个读性能就太差了;那么如果我想获取磁盘读性能最高,应该怎么做呢?把数据全部排序就行了,B+树就是这样的结构,但B+树的写性能太差了,需要提升写,可以放弃部分磁盘读性能,怎么办呢?

    简单,那就划分很多个小的有序结构,比如每m个数据,在内存里排序一次,下面100个数据,再排序一次……这样依次做下去,我就可以获得N/m个有序的小的有序结构,在查询的时候,因为不知道这个数据到底是在哪里,所以就从最新的一个小的有序结构里做二分查找,找得到就返回,找不到就继续找下一个小有序结构,一直到找到为止。

    很容易可以看出,这样的模式,读取的时间复杂度是(N/m)*log2N,读取效率是会下降的,这就是LSM的根本思路。当然RocksDB为了优化效率又引入了bloomfilter,compact机制,感兴趣可以阅读RocksDB的wiki:

LSM好处

  • B+索引树和log型(append)文件操作(数据库WAL日志)是数据读写的两个极端。B+树读效率高而写效率差;log型文件操作写效率高而读效率差;因此要在排序和log型文件操作之间做个折中,于是就引入了log-structed merge tree模型,通过名称可以看出LSM既有日志型的文件操作,提升写效率,又在每个sstable中排序,保证了查询效率。

存储结构

实现方式

  1. 当有写操作(或update操作)时,写入位于内存的buffer,内存中通过某种数据结构(如skiplist、vertor等)保持key有序

  2. 一般的实现也会将数据追加写到磁盘Log(wal)文件,以备必要时恢复

  3. 内存中的数据定时或按固定大小地刷到磁盘,更新操作只不断地写到内存,并不更新磁盘上已有文件 compact操作

  4. 随着越来越多写操作,磁盘上积累的文件也越来越多,这些文件不可写且有序

  5. 定时对文件进行合并操作(compaction),消除冗余数据,减少文件数量

  • LSM存储结构的写操作,只需更新内存,内存中的数据以块数据形式刷到磁盘,是顺序的IO操作,另外磁盘文件定期的合并操作,也将带来磁盘IO操作。

  • LSM存储结构的读操作,先从内存数据开始访问,如果在内存中访问不到,再顺序从一个个磁盘文件中查找,由于文件本身有序,并且定期的合并减少了磁盘文件个数,因而查找过程相对较快速。

  • 合并操作是LSM实现中重要的一环,LevelDB、Cassandra中,使用基于层级的合并方式(Levelled compaction),生成第N层的时候,对N-1层的数据进行排序,使得每层内的数据文件之间都是有序的,但最高层除外,因为该层不断有数据文件产生,因而只是数据文件内部按key有序。

  • 除最高层外,其他层文件间数据有序,这也加速了读过程,因为一个key对应的value只存在一个文件中。假设总共有N层,每层最多K个数据文件,最差的情况下,读操作先遍历K个文件,再遍历每层,共需要K+(N-1)次读盘操作。

LSM Paper解读

为什么要有LSM-TREE

  • 对于大量写操作B-Tree的写入会带来大量的IO开销,存在维护索引、排序写成本,LSM-Tree的核心思想是将写入推迟(Defer)并转换为批量(Batch)写,先将大量写入缓存在内存中,当积攒到一定程度后,批量写入文件中充分利用每一次IO。

LSM-Tree大量写优于B-Tree的原因

  1. multi-page block:不同于B-Tree,LSM-Tree的延时写(数据可以积攒)可以有效的利用multi-page block,在Rolling Merge的过程中,一次从C1中读出多个连续pages,与C0进行Merge,然后一次向C1写回这些连续pages,这样有效利用单次I/O完成多个pages的读写(B-Tree在此场景下无法利用multi-page的优势)

  2. batch:同样因为延迟写,LSM-Tree可以在Rolling Merge中,通过一次I/O批量向C1写入C0多条数据,那么这多条数据就均摊了这一次I/O,减少磁盘的I/O开销

技术分享
LSM paper
RocksDBwiki