数据结构:log-structed结构MemTableSSTable

log-structed结构

📌

Log-Structured 结构 - mzjnumber1 - 博客园

Log-structed结构介绍

Log-Structured 结构,有时候也会被称作是 Append-only Sequence of Data,因为所有的写操作都会不停地添加进这个数据结构中,而不会更新原来已有的值,这也是 Log-Structured 结构的一大特性。

比如说,Google 的三驾马车之一,Bigtable 文件系统的底层存储数据结构采用的就是Log-Structured结构, MongoDB 和 HBase 这类的 NoSQL 数据库,它们的底层存储数据结构其实也是 Log-Structured 结构。

一个常见的问题应用:

假设一个视频网站需要一个统计视频观看次数的功能,如果设计的话,会采用哪种数据结构呢?

可以运用哈希表这个数据结构,以视频的 URL 作为键、观看次数作为值,保存在哈希表里面。所有保存在哈希表里面的初始值都为 0,表示并无任何人观看,而每次有人观看了一个视频之后,就将这个视频所对应的值取出然后加 1。刚开始的时候,这个设计思路可能运行得很好。可当用户量增大了之后,会发现在更新哈希表的时候必须要加锁,不然的话,大量的这种并行 +1 操作可能会覆盖掉各自的值。

那有没有方法可以不用顾及写操作的高并发问题,同时也可以最终获得一个准确的结果呢?答案就是使用 Log-Structured 结构。

上面是 Log-Structured 结构的本质了(写操作不更新而添加到后面)

(1)一个数组不可能在内存中无限地增长下去,如何处理呢?

(2)如果每次想要知道结果,就必须遍历一遍这样的数组,时间复杂度会非常高,那该怎么优化呢?

(3)平衡树是如何被应用在里面的呢?

Log-Structured 结构的优化

首先,可以定义一个大小为 N 的固定数组,我们称它为 Segment,一个 Segment 最多可以存储 N 个数据,

当有第 N+1 个数据需要写入 Log-Structured 结构的时候,我们会创建一个新的 Segment,然后将 N+1 个数据写入到新的 Segment 中。以下图为示,定义一个 Segment 的大小为 16,当 Segment 1 写满了 16 个数据之后,会将新的数据写入到 Segment 2 里。

Log-Structured 结构还是一直在往内存里添加数据,并没有解决最终会消耗完内存的问题。这时候就到Compaction 大显身手的时候了,在当 Segment 到达一定数量的时候,compaction 会通过后台的线程,把不同的 Segments 合并在一起。假设我们定义当 Segment 的数量到达两个的时候,后台线程就会执行 Compaction 来合并结果。

在 Compaction 完成了之后,对于结果的读取就可以从 Compacted Segment 里面读取了。因为这时候所有的结果已经存放在 Compacted Segment 里面了,所以就可以删除 Segment 1 和 Segment 2 来腾出内存空间了。

整个 Compaction 的过程会不断地递归进行下去,当 Compacted Segment 满了以后,后台线程又可以对 Compacted Segment 进行 Compaction 操作,再次合并所有结果。

Compaction的位置和时机:

Log-Structured 存储系统中,Compaction的核心操作是合并多个 **SSTable(Sorted String Table)**文件,这个过程确实需要读取多个 SSTable 的数据,并进行排序、去重和合并。然而,是否将所有数据完全加载到内存中,以及如何高效地执行合并操作,取决于系统的设计和优化策略。以下是详细的说明。

  1. Compaction 的基本流程

(1)选择需要合并的 SSTable:根据 Compaction 策略(如层级 Compaction 或分层 Compaction),选择需要合并的 SSTable 文件。

(2)读取 SSTable 数据:从磁盘读取选中的 SSTable 文件。

(3)合并数据:将多个 SSTable 的数据按键排序、去重(保留最新的值)并合并。

(4)写入新的 SSTable:将合并后的数据写入新的 SSTable 文件。

(5)清理旧的 SSTable:删除旧的 SSTable 文件,释放磁盘空间。

  1. 数据读取和合并的方式

在 Compaction 过程中,是否需要将所有数据加载到内存中,取决于系统的设计和优化策略。

(1)全内存合并

  • 过程:将所有需要合并的 SSTable 文件完全加载到内存中,然后在内存中进行排序、去重和合并。

(2)外部排序合并(External Merge Sort)

  • 过程
  1. 将每个 SSTable 文件的数据分块读取到内存中。
  2. 对每个块进行排序(如果未排序)。
  3. 使用多路归并(Multiway Merge)算法,将多个有序块合并成一个更大的有序文件。
  4. 将合并后的数据写入新的 SSTable 文件。
  • 优点

  • 内存占用低,适合大规模数据场景。

  • 可以处理远大于内存容量的数据。

  • 缺点

  • 实现复杂度较高。

  • 由于涉及磁盘 I/O,速度比全内存合并慢。

memtable

memtable内存中的数据结构(表),用于临时存储新写入的数据。

memtable Memory Table,即内存表,它的作用是高效地缓存新写入的数据,并在达到一定大小后将数据写入磁盘,形成有序的文件(SSTable)。

  1. memtable 的作用

(1)临时存储新写入的数据:所有新写入的数据首先会被插入到 memtable 中。

(2)保持数据有序:memtable 通常是一个有序的数据结构(如平衡二叉查找树、跳表等),数据在插入时会自动按键排序。由于 memtable 位于内存中,读写速度非常快。

(3)为后续写入磁盘做准备:当 memtable 达到一定大小时,它会被冻结并写入磁盘,形成有序的 SSTable。

memtable 通常使用以下数据结构实现:

  • 平衡二叉查找树:红黑树,AVL 树等。这些树结构可以保证数据的有序性,并且插入、删除和查找操作的时间复杂度为 O(log n)。
  • 跳表(SkipList):跳表是一种概率性的有序数据结构,它的性能与平衡树类似,但实现更简单。
  • 其他有序结构:如 B 树、B+ 树等。

memtable 在 LSM 树中的典型工作流程:

  1. 写入数据

当新数据写入时,首先会被插入到 memtable 中,memtable 会将其按键排序存储。

  1. 读取数据

当需要读取数据时,系统会先检查 memtable。如果数据在 memtable 中,则直接返回。如果 memtable 中没有找到数据,则会继续检查磁盘上的 SSTable。

  1. memtable 写满

当 memtable 的大小达到阈值时,它会被冻结(变为不可变),并创建一个新的 memtable 来接收新写入的数据。被冻结的 memtable 会被写入磁盘,形成一个有序的 SSTable。

  1. Compaction

当磁盘上有多个 SSTable 时,系统会定期进行 Compaction,将多个 SSTable 合并成一个更大的 SSTable。Compaction 过程中会去除重复的键和删除标记,从而优化存储空间和读取性能。

在memtable中插入重复键的元素时,常见的处理方式包括:

1.覆盖旧值(默认行为)。2.保留历史记录(多版本控制)。3.自定义冲突解决策略。

SSTable

SSTable(Sorted String Table)数据结构是在 Log-Structured 结构的基础上,多加了一条规则,就是所有保存在 Log-Structured 结构里的数据都是键值对,并且键必须是字符串,在经过了 Compaction 操作之后,所有的 Compacted Segment 里保存的键值对都必须按照字符排序。

当我们要查找一个单词出现的次数时,可以遍历所有的 Compacted Segment,因为所有数据都是按照字符串排好序的,如果当遍历到的字符串已经大于我们要找的字符串时,就表示并没有出现过这个单词。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/7582.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开发环境搭建-3:配置 nodejs 开发环境 (fnm+ node + pnpm)

在 WSL 环境中配置:WSL2 (2.3.26.0) Oracle Linux 8.7 官方镜像 node 官网:https://nodejs.org/zh-cn/download 点击【下载】,选择想要的 node 版本、操作系统、node 版本管理器、npm包管理器 根据下面代码提示依次执行对应代码即可 基本概…

HTB:Support[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用ldapsearch…

洛谷P1017 [NOIP2000 提高组] 进制转换

题目链接:P1017 [NOIP2000 提高组] 进制转换 - 洛谷 | 计算机科学教育新生态 题目难度:普及一 题目分析:这是道数学题,我们都知道,首先按照10进制转成n进制的做法:对这个数不断除以n,将余数一一…

php代码审计2 piwigo CMS in_array()函数漏洞

php代码审计2 piwigo CMS in_array()函数漏洞 一、目的 本次学习目的是了解in_array()函数和对项目piwigo中关于in_array()函数存在漏洞的一个审计并利用漏洞获得管理员帐号。 二、in_array函数学习 in_array() 函数搜索数组中是否存在指定的值。 in_array($search,$array…

【2024年华为OD机试】(A卷,200分)- 查找树中元素 (JavaScriptJava PythonC/C++)

一、问题描述 题目解析 题目描述 题目要求根据输入的坐标 (x, y) 在树形结构中找到对应节点的内容值。其中: x 表示节点所在的层数,根节点位于第0层,根节点的子节点位于第1层,依此类推。y 表示节点在该层内的相对偏移,从左至右,第一个节点偏移为0,第二个节点偏移为1,…

WPS数据分析000006

一、排序 开始→ 排序 同文件→选项→自定义序列→输入序列 二、筛选 高级筛选 条件区域要与列表区域一样。 三、条件格式

基于微信小程序的英语学习交流平台设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…

记录一个连不上docker中的mysql的问题

引言 使用的debian12,不同发行版可能有些许差异,连接使用的工具是navicat lite 本来是毫无思绪的,以前在云服务器上可能是防火墙的问题,但是这个桌面环境我压根没有使用防火墙。 直到 ying192:~$ mysql -h127.0.0.1 -uroot ERROR 1045 (28…

SpringBoot基础概念介绍-数据源与数据库连接池

🙋大家好!我是毛毛张! 🌈个人首页: 神马都会亿点点的毛毛张 毛毛张今天介绍的SpringBoot中的基础概念-数据源与数据库连接池,同时介绍SpringBoot整合两种连接池的教程 文章目录 1 数据库与数据库管理系统2 JDBC与数…

深度学习 Pytorch 单层神经网络

神经网络是模仿人类大脑结构所构建的算法,在人脑里,我们有轴突连接神经元,在算法中,我们用圆表示神经元,用线表示神经元之间的连接,数据从神经网络的左侧输入,让神经元处理之后,从右…

GCC之编译(8)AR打包命令

GCC之(8)AR二进制打包命令 Author: Once Day Date: 2025年1月23日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章请查看专栏: Linux实践记录_Once-Day的博客-C…

SpringBoot统一功能处理

一.拦截器 1.拦截器的简单介绍 拦截器是Spring框架提供的核⼼功能之⼀,主要⽤来拦截⽤⼾的请求,在指定⽅法前后,根据业务需要执⾏预先设定的代码. 2.使用 (i).定义拦截器: (ii).注册拦截器 (iii).拦截路径 (iv).实行流程 3.登录校验 4.DispatcherServlet源码&…

31、Java集合概述

目录 一.Collection 二.Map 三.Collection和Map的区别 四.应用场景 集合是一组对象的集合,它封装了对象的存储和操作方式。集合框架提供了一组接口和类,用于存储、访问和操作这些对象集合。这些接口和类定义了不同的数据结构,如列表、集合…

Unity|小游戏复刻|见缝插针1(C#)

准备 创建Scenes场景,Scripts脚本,Prefabs预制体文件夹 修改背景颜色 选中Main Camera 找到背景 选择颜色,一种白中透黄的颜色 创建小球 将文件夹里的Circle拖入层级里 选中Circle,位置为左右居中,偏上&…

Word 中实现方框内点击自动打 √ ☑

注: 本文为 “Word 中方框内点击打 √ ☑ / 打 ☒” 相关文章合辑。 对第一篇增加了打叉部分,第二篇为第一篇中方法 5 “控件” 实现的详解。 在 Word 方框内打 √ 的 6 种技巧 2020-03-09 12:38 使用 Word 制作一些调查表、检查表等,通常…

Android Studio:视图绑定的岁月变迁(2/100)

一、博文导读 本文是基于Android Studio真实项目,通过解析源码了解真实应用场景,写文的视角和读者是同步的,想到看到写到,没有上帝视角。 前期回顾,本文是第二期。 private Unbinder mUnbinder; 只是声明了一个 接口…

第13章 深入volatile关键字(Java高并发编程详解:多线程与系统设计)

1.并发编程的三个重要特性 并发编程有三个至关重要的特性,分别是原子性、有序性和可见性 1.1 原子性 所谓原子性是指在一次的操作或者多次操作中,要么所有的操作全部都得到了执行并 且不会受到任何因素的干扰而中断,要么所有的操作都不执行…

算法中的移动窗帘——C++滑动窗口算法详解

1. 滑动窗口简介 滑动窗口是一种在算法中常用的技巧,主要用来处理具有连续性的子数组或子序列问题。通过滑动窗口,可以在一维数组或字符串上维护一个固定或可变长度的窗口,逐步移动窗口,避免重复计算,从而提升效率。常…

基于SpringBoot的网上考试系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

【java数据结构】map和set

【java数据结构】map和set 一、Map和Set的概念以及背景1.1 概念1.2 背景1.3 模型 二、Map2.1 Map说明2.2 Map的常用方法 三、Set3.1 Set说明3.2 Set的常用方法 四、Set和Map的关系 博客最后附有整篇博客的全部代码!!! 一、Map和Set的概念以及…