mysql、redis、zk、kafka、es、linux持久化横评
2023-07-05 09:37:26 0 举报
AI智能生成
知识要点和原理解析,详细信息和图片均在黄色图标的注释中,鼠标移动到黄色图标上即会显示,图片加载有时较慢。
作者其他创作
大纲/内容
mysql
InnoDB总体结构
内存部分由多个缓冲区构成
redolog与binlog两阶段提交
图示
buffer pool数据落盘
数据库关闭时,将所有脏页刷新到磁盘,这是默认的方式
Master Thread操作,这个主线程会每秒、每10秒从脏页列表刷新一定比例的页到磁盘,这是个异步的操作,不会阻塞查询
buffer pool中的free列表空闲页不足时,需要刷新一部分来自LRU列表的脏页
redo log文件不可用时,需要强制刷新一部分,为了保证redo log的循环利用
内存回收
3种页
1、free page
2、clean page
3、dirty page
针对这3种页,InnoDB使用3种链表维护
free list
flush list
lru list
脏页刷盘
1、从LRU 链表的冷数据区刷新部分页面到磁盘
2、从 flush 链表中刷新一部分页面到磁盘
3、主动刷盘内存池中被淘汰的脏页
Buffer Pool缓存淘汰
使用LRU会遇到的问题
预读
大量数据涌入
解决方法
冷热分离LRU
优化点1:midpoint
优化点2:old_blocks_time
优化点3:减少热页在链表移动
磁盘部分包括各种表空间
行结构和页结构
ibd文件的逻辑结构
Tablespace
Segment
段和索引是一一对应的关系
段不对应表空间的某一连续物理区域
问题
一个使用 InnoDB 表只有一个聚簇索引,一个索引对应两个段,每个段都是以区为单位申请空间,是否意味着一个新创建的表即使没什么数据也要占用2个空闲区(2M空间)?并且每新建一个索引就会多申请2M的空间?如果真的是这样分配空间,对于一些只有几条数据的表而言实在是太浪费空间。
某个段分配空间的策略
Extent
问题
为什么提出区的概念,并用区管理页?
如果没有区
Page
InnoDB的页结构
用户记录 和 User Records 堆
用户记录的物理结构——堆
Infimum 和 Supremum记录
用户记录的逻辑结构——单向链表
软删除
页目录 Page Directory
页目录的构建过程
页目录的每一个槽本质上就指向每个分组(的组长)的指针
页面头部 Page Header
文件头部 File Header
数据页与记录的关系
Row
索引
特性
B+树的每一层都会形成一个双向链表
叶子节点是数据页,存储普通用户记录
非叶子节点也是数据页,存储目录项记录
目录项记录跟用户记录存储结构一致,只是存储的数据略有差异
目录项记录至少有3个固定的列+隐藏列
索引是有序的
叶子节点之间是有序的
叶子节点内是有序的
同层非叶子节点之间是有序的
非叶子节点内是有序的
从数据页变成索引这件事
数据页
数据页结构
空闲空间
双向链表
数据页目录
索引
页分裂
主键目录
索引页
现在整个搜索过程就十分简单了
Innodb索引结构和方案
InnoDB的索引方案
用户记录页
目录页
目录页的页内查找:二分查找
目录页也会发生页分裂
主键索引(聚簇索引)和普通索引的区别
二级索引
联合索引的页
redis
对象封装
redisObject
两层结构
六种内部数据结构
底层的实现:dict,sds,ziplist,quicklist,skiplist,intset
五种外部数据类型
暴露给外部的调用接口:string,list,hash,set,sorted set
字段
type
OBJ_STRING
OBJ_LIST
OBJ_SET
OBJ_ZSET
OBJ_HASH
encoding
lru
refcount
ptr
作用
redisObjec是联结两个层面的数据结构的桥梁
为多种数据类型提供一种统一的表示方式
允许同一类型的数据采用不同的内部表示,从而在某些情况下尽量节省内存
支持对象共享和引用计数。当对象被共享的时候,只占用一份内存拷贝,进一步节省内存
持久化
RDB
触发过程
手动
save 命令
阻塞 Redis 服务,直到整个 RDB 持久化完成,不建议
bgsave 命令
该模式下的 RDB 持久化由子进程完成,非阻塞
自动
save m n
RDB 数据恢复
优缺点
优点
由于 RDB 文件是一个非常紧凑的二进制文件,所以加载的速度快于 AOF 方式
fork 子进程方式,不会阻塞
RDB 文件代表着 Redis 服务器的某一个时刻的全量数据,所以它非常适合做冷备份和全量复制的场景
缺点
没办法做到实时持久化,会存在丢数据的风险
AOF(默认关闭)
目的
解决数据持久化的实时性
执行流程
命令写入
文件同步
文件重写
手动触发
自动触发
优缺点
优点
相比于 RDB,AOF 更加安全,默认同步策略为 everysec 即每秒同步一次,所以顶多我们就失去一秒的数据
根据关注点不同,AOF 提供了不同的同步策略,我们可以根据自己的需求来选择
AOF 文件是以 append-only 方式写入,相比如 RDB 全量写入的方式,它没有任何磁盘寻址的开销,写入性能非常高
缺点
由于 AOF 日志文件是命令级别的,所以相比于 RDB 紧致的二进制文件而言它的加载速度会慢些
AOF 开启后,支持的写 QPS 会比 RDB 支持的写 QPS 低
RDB 和 AOF 混合模式
RDB-AOF 混合持久化
1、在 AOF 重写阶段创建一个同时包含 RDB 数据和 AOF 数据的 AOF 文件,其中 RDB 数据位于 AOF 文件的开头,RDB存储了服务器开始执行重写操作时 Redis 服务器的数据状态(RDB 快照方案)。
2、重写操作执行之后的 Redis 命令(即已存储当前RDB之后的命令),则会继续 append 在 AOF 文件末尾,即 RDB 数据之后(AOF 日志追加方案),一般这部分数据都会比较小
1. Redis 重启的时候,则可以先加载 RDB 的内容,然后再加载 AOF 的日志内容。
zk
zk持久化
内存中的数据
事务日志
日志文件
数据快照
为什么需要快照
快照数据主要时为了快速恢复
数据恢复
恢复数据的时候,先恢复快照数据,再通过增量恢复事务日志中的数据。
kafka
Kafka Broker 写入数据的过程
隐患:如果数据写入 PageCache 后 Kafka Broker宕机会怎样?机子宕机/掉电?
Kafka Broker 宕机: 消息不会丢失
机子宕机/掉电: 消息会丢失
拓展:Kafka 日志刷盘机制
推荐采用默认值,即不配置该配置,交由操作系统自行决定何时落盘,以提升性能。
相关配置
针对 broker 配置
针对 topic 配置
查看 Linux 后台线程执行配置
索引及日志文件
文件存储机制
每个分区就对应一个Log对象,在物理磁盘上则对应于一个子目录
日志段是Kafka保存消息的最小载体
kafka利用分段+索引的方式来解决查找效率问题
参数log.segment.bytes
限定了每个日志段文件的大小,最大为1GB。
超过该限制会进行日志切分滚动log rolling
active log segment:正在被写入的日志
ConcurrentSkipListMap
索引机制
分类
偏移量索引文件
格式
index文件
如何通过offset找到对应的消息?
时间戳索引文件
格式
查找
查找原理
索引项
索引项间隔:log.index.interval.bytes
索引文件以稀疏索引的方式来构建
稀疏索引是通过MappedByteBuffer将索引文件映射到内存中(pageCache),加快索引的查询速度
索引文件排序
按照位移/时间戳升序排序
用二分法查找索引,时间复杂度是O(logN)
检索原理
稀疏矩阵
ConcurrentSkipListMap
ConcurrentSkipListMap的方法
MMAP(MappedByteBuffer)
有限内存加载所有segment?
检索整体流程图
日志定位过程
例子
检索总结
定位索引段segment时使用跳表ConcurrentSkipListMap
索引文件.index使用稀疏索引存储,每4k数据一个索引
使用二分法检索文件
索引文件使用MMAP映射到pageCache
日志切分
每个LogSegment中的日志数据文件大小均相等
改进后的二分法
log文件存储格式
offset index
传统二分法源码
问题
改进后的二分法
源码
效果
为什么设置热区大小为8192字节
es
索引层面的写入、更新、删除、合并
写入过程
过程分解
首先,document会被写入in-memory buffer和translog日志文件
每隔1秒,执行一次refresh操作
refresh操作完成后,buffer会被清空
图解
为什么说Elasticsearch是准实时(NRT,near real-time)?
实时查询 - GetById
Translog 事务日志
写入机制
图解
flush过程
触发flush操作
第一步,将buffer中的现有数据refresh到os cache中生成segment,清空buffer
把之前所有没有落盘的 segment 强制刷盘,确保写入物理文件。
创建一个提交点,记录这次提交对应的所有 segment,写入 commit point 文件。
清空 Translog,因为 Segment 都已经踏实落地了,之前的 Translog 就不需要了。
触发清理动作的2个条件
大小触发设定的阈值;
30分钟
删除和更新
update流程(部分更新)
versionMap
主要用途在数据变更时的校验
_id与_uid的联系
segment 合并
定期合并
合并完成时的活动
合并也是在内存中完成的,此时数据还没有写到磁盘中
整体流程图
图1
图2
memory buffer的倒排索引,则必须等Segment内所有文档全部写入完毕后,会先对Term进行一个全排序,之后才能构建索引,所以必须要有一个memory-buffer先缓存所有文档。
Elasticsearch的写入流程特性
可靠性
一致性
原子性
实时性
隔离性
linux
文件系统
一切皆文件
磁盘结构
盘面
磁道
扇区
磁盘的基本单位
块
文件系统操作文件的最小单位
Linux文件系统
分为两层
VFS(虚拟文件系统)
VFS在linux架构中的位置
具体文件系统
虚拟文件系统四大对象
1、超级块
2、索引节点:inode
inode描述
一个inode可以有多个文件名(目录项:dentry)来对应它
inode能描述文件占用的块数
inode描述了文件大小和指向数据块的指针
通过i节点实现文件的逻辑结构和物理结构的转换
inode怎样生成的?
inode和文件的关系?
3、目录项:dentry
目录项和索引节点的关系:多对一
目录项和目录是一个东西吗?
4、逻辑块
文件数据是如何存储在磁盘的?
inode保存指向逻辑块的指针:一对多
文件分配方式
连续分配
优点
缺点
链式分配
隐式链接
优点
缺点
显式链接
优点
缺点
索引分配
优点
文件的创建、增大、缩小很方便
不会有碎片的问题
支持顺序读写和随机读写
缺点
如果文件很大
链式索引块
多级索引块
空闲空间的管理
空闲表法
优点
缺点
碎片空间
空闲链表法
优点
无碎片空间
缺点
不能随机访问,工作效率低
数据块的指针消耗了一定的存储空间
位图法
索引节点、目录项以及文件数据关系图
文件的存储
块组
目录的存储
内存管理
虚拟内存、内存管理单元(MMU)、物理内存
映射关系管理
分段
分段机制会把程序的虚拟地址分成 4 个段
好处
能产生连续的内存空间
不足之处
内存碎片
内存交换的效率低
分页
怎么解决分段的内存碎片、内存交换效率低的问题?
如果内存空间不够:LRU
虚拟地址和物理地址是如何映射的?
举例
简单的分页有什么缺陷呢?
多级页表
二级页表空间分析
局部性原理
不分级为何无法节省内存
页表缓存TLB(Translation Lookaside Buffer)
内存回收
三种回收方式
1、回收内核中的缓存
2、swap 机制
3、触发 OOM(Out Of Memory) 机制
swap机制原理
哪些进程的内存交换到硬盘中?
匿名内存页(数据段、堆段 和 栈段)
LRU 内存淘汰算法
主要构成
active_list
inactive_list
PG_referenced标志位
流程
申请一个匿名内存页
匿名内存页被进程访问
内存淘汰过程
活跃链表 的内存页也有衰退的过程
用户态与内核态的内存空间
虚拟内存
0 条评论
下一页