手写分布式存储系统v0.2版本

引言

上回说到 手写分布式存储系统v0.1版本 ,已经实现了通过监听TCP端口并将数据写到本地磁盘的功能,今天咱们就继续往上面添砖加瓦

v0.2版本大致做以下功能

  • 实现滚动写文件

  • 代码优化

一、滚动写文件实现

由于咱们写文件是用的mmap进行文件写入,而mmap自身原因最多只能映射到不大于2G的文件。因此在一个磁盘文件写满后,咱们需要滚动写到一个新的文件中,基本上所有分布式存储系统都是这么实现的,如kakfa、pulsar、rocketmq等等。那咱们也自己尝试实现下,大致逻辑如下
在这里插入图片描述

这个过程中有几个点需要考虑

  • 如何判断文件写满了
  • 滚动前后文件名的变化规则

第一点可以考虑在内存中维护一个整型记录当前文件的大小,否则每次写数据时判断是否写满都要去查下linux会影响性能

第二点文件名变化规则的设计方式有较多中,例如每次写新的文件名都用最新的等。参考几个系统的实现后决定采用写指定名字的文件例如 “file”,当这个文件写满1个G时,将“file”改名为“file”加当前时间如“file-20240202”,然后再新建一个名为“file”的文件进行写入。这样就能保证“file”这个文件永远都是当前正在写入的文件,核心代码如下

    private boolean rollingFile() throws IOException {preFilepath =fileName+"-"+LocalDateTime.now().toString().replace(":","-").substring(0,19);File preFile = new File(preFilepath);boolean preFileExists = preFile.exists();if (!preFileExists) {this.fileChannel.force(false);boolean rename = file.renameTo(preFile);if (rename) {this.fileChannel = new RandomAccessFile(new File(fileName), "rw").getChannel();this.mappedByteBuffer = this.fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, fileSize);WROTE_POSITION_UPDATER.set(this, 0);return true;} else {LOG.error("TieredIndexFile#rollingFile: rename current file failed");return false;}}return false;}

二、代码优化

由于v0.1版本中实现的比较莽,因此现在需要进行一个简单的重构。重构后大致逻辑可以参考下面这张不规范的UML图,首先是抽象出一个LifecycleComponent接口,由于除了网络、持久化服务之外,未来咱们可能还会有其他的服务例如监控、插件服务等等,因此咱们需要对这些服务做一层统一的抽象,所有这些服务都要提供服务启动和服务停止的接口,这样设计之后再服务启动/停止时只需要对LifecycleComponent集合列表进行统一的启动/停止操作即可,代码维护起来也很舒服。

网络方面是通过NetServiceImpl方法初始化并启动Netty引导类ServerBootstrap,ServerBootstrap启动后会监听Linux机器的网络端口,在监听到有请求时会交给ServerHandler 进行处理,在ServerHandler这里可以调用LocalDataStorageImpl方法进行数据持久化,LocalDataStorageImpl是数据持久化的统一入口,咱们针对mmap写入方式抽象并实现了DefaultMappedFile,提供了真正的mmap写磁盘操作。基本大致逻辑就是如此,尽量不做过度的设计,好的系统是演变过来的,等未来发展到一定阶段后再根据情形进行分析优化
在这里插入图片描述

三、功能演示

  1. 开发完后,咱们就可以开始进行演示了,启动服务后当在控制台看到以下信息就知道服务已经正常启动,此时就可以发数据给服务端了
    在这里插入图片描述

  2. 通过指令能看到已经在目录下创建好对应的文件,由于是通过mmap方式写的数据,因此虽然咱们还没写数据到文件内,但是可以看到文件大小已经是100Byte了,这也是mmap的特点
    在这里插入图片描述

  3. 通过以下指令往8888端口发送数据
    (echo 'are you ok?'; sleep 2) | telnet 127.0.0.1 8888

  4. 通过控制台能够看到数据有写到磁盘,并且内存中维护的文件里存放数据的大小也在增加
    在这里插入图片描述

  5. 重复多次第4步,可以看到日志显示已到达文件大小触发文件滚动动作
    在这里插入图片描述

  6. 再看看linux文件系统可以看到,已经创建对应的文件testWrite-2024-02-02T19-35-20
    在这里插入图片描述

  7. 打印一下可以清晰的看到咱们刚刚请求的内容都被正确的持久化到磁盘中了
    在这里插入图片描述

四、总结

上面基本上就是 v0.2 版本的内容了,不难但是你会发现使用一个分布式存储系统、看它的源码的体验,跟你自己实现一遍是完全不同的,一个现成的组件就像是一架飞机,你看得到它的机翼、发动机等等,你知道它是这样设计的;但,它为什么是这样设计的呢?那样不可以吗,这类问题恐怕会想的比较少或者虽然想了一下但是转头就忘了。但是当你自己设计去实现的过程中,你会遇到种种问题需要你去反复思考以及做取舍等等,这些都是你真正意义上成长的过程,甚至有时还会顿悟为什么那个东西人家要这样设计,这些都是无比令人振奋的事情,这不就是生命的意义吗

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

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

相关文章

索引的设计原则(MySQL)

文章目录 文章目录 前言 一、搜索的索引列 二、使用唯一索引 三、使用短索引 四、最左前缀原则 五、不要过度使用 六、尽量使用主键索引 ​​​​​ 前言 索引的设计需要遵循一些原则,创建索引时遵循这些原则,有利于提升查询效率。 一、搜索的索引列 创建…

解决ModuleNotFoundError: No module named ‘pysqlite2‘

目录 一、问题描述 二、问题分析 三、解决方法 四、参考文章 一、问题描述: 新建conda编译环境。安装Jupyter后打不开,报错: 二、问题分析: 缺少sqlite3动态链接库 三、解决方法: SQLite Download Page 下载…

组播目的地址

路由器收到目的地址为224.0.0.5和239.0.0.5的组播报文如何处理? 224.0.0.5为永久组地址,是IANA为路由协议预留的IP地址(也称为保留组地址),用于标识一组特定的网络设备,供路由协议,目前被分配于OSPF协议使用,运行了OSPF协议的网络设备默认都会加入该组播组。 当路由器…

数字地球开放平台农作物长势监测解决方案

利用遥感技术进行产量预测是一种高效而准确的方法,通过监测植被的生长状况、土地利用、气象等因素,可以为农业决策提供有力支持。数字地球开放平台拥有200颗卫星,为您提供一站式卫星遥感服务。 数字地球开放平台将为您介绍一般遥感技术在农作…

游戏开发丨基于Panda3D的迷宫小球游戏

文章目录 写在前面Panda3D程序设计程序分析运行结果系列文章写在后面 写在前面 本期内容 基于panda3d的迷宫中的小球游戏 所需环境 pythonpycharm或anacondapanda3d 下载地址 https://download.csdn.net/download/m0_68111267/88792121 Panda3D Panda3D是一种开放源代码…

如何选择最适合的服务器

许多朋友想做一些网站,应用,游戏,小程序等等,都需要接触一个基础,就是服务器。服务器相当于一台24小时不关机的联网电脑,浏览网页或者应用相当于用户在访问这台电脑里的文件。那么如何选择最适合自己的服务…

在微服务项目中,实现无停机更新有哪些方法和策略?

在微服务项目中,确保线上更新不停掉服务是非常关键的,以保障系统的可用性。以下是一些方法和策略,可以帮助实现无停机更新: 蓝绿部署(Blue-Green Deployment): 在蓝绿部署中,维护两个…

【Java高级】通过CompletableFuture类异步、并行获取数据库数据

1. CompletableFuture类简介 CompletableFuture 类是 Java 中用于异步编程和处理异步任务的工具类。它是 Java 8 引入的一部分,提供了一种方便的方式来处理异步操作,例如并行执行多个任务、等待多个任务完成等。 CompletableFuture 可以通过 runAsync …

【Java 数据结构】对象的比较

Java中对象的比较 1. PriorityQueue中插入对象2. 元素的比较2.1 基本类型的比较2.2 对象比较的问题 3. 对象的比较3.1 覆写基类的equals3.2 基于Comparble接口类的比较3.3 基于比较器比较3.4 三种方式对比 4. 集合框架中PriorityQueue的比较方式5. 使用PriorityQueue创建大小堆…

【AI_Design】Midjourney学习笔记

目录 后缀解析Promot合格使用prompt关键词描述 关键词化合作用关键词网站推荐 联合Chatgpt使用总结 后缀解析 –ar:宽高比设置–c:多样性设置(数值0-100,默认值0)–s:风格化设置(数值0-1000&am…

Java面试——计网篇

一、基础篇 1、 TCP/IP 网络模型 对于同一台设备上的进程间通信,有很多种方式,比如有管道、消息队列、共享内存、信号等方式,而对于不同设备上的进程间通信,就需要网络通信,而设备是多样性的,所以要兼容多…

结构体--共用体--枚举 之难点——链表 奋力学习嵌入式的第十六天

结构体 注意: 1.结构体类型 可以定义在 函数里里面 但是此时作用域就被限定在该函数中 2.结构体定义形式 //形式一 限定一类型 后定义变量 struct stu { ... }; struct stu s; //形式二 定义类型的同时 定义变量 struct stu { ... }s1,s2,*s3,s4[10]; struc…

【说明】Nginx配置反向代理但是不包含某个地址

【说明】Nginx配置反向代理但是不包含某个地址 配置 反向代理 /api 这个路径 但是不包含 /api/wechat/service 这个请求 www.weixin.com/api/wechat/service www.weixin.com/api/getUser OK location ^~ /api(?!/wechat/service) { // OK }

影院购票|电影院订票选座小程序|基于微信小程序的电影院购票系统设计与实现(源码+数据库+文档)

电影院订票选座小程序目录 目录 基于微信小程序的电影院购票系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户功能实现 2、管理员功能实现 (1)影院信息管理 (2)电影信息管理 (3)已…

STM32F1 - 存储器映射

Memory mapping 1> 外设内存地址映射2> GPIO寄存器映射3> 存储器访问 1> 外设内存地址映射 1> STM32F103ZET6的地址线位宽为32位,所以寻址空间为4GB (2 ^ 32 4GB); 2> STM32将,Flash,SR…

PageHelper.startPage(pageNum, pageSize);分页总数不正确,避坑!

今天在调用一个查询列表的接口时,分页总数老是查的不正确: 当pageSize选择10时,总数只有10条 当pageSize选择20时,总数只有15条 实际上总数为15条实在正确的,然后取看代码: Overridepublic AjaxResult pro…

中科大计网学习记录笔记(四):Internet 和 ISP | 分组延时、丢失和吞吐量

前言: 学习视频:中科大郑烇、杨坚全套《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》课程 该视频是B站非常著名的计网学习视频,但相信很多朋友和我一样在听完前面的部分发现信…

32GPIO输入&按键控制LED&光敏控制蜂鸣器

目录 一.硬件 二.硬件电路 三.C语言基础 四.代码实现 1.按键控制LED (1)自己的代码逻辑 (2)视频的代码逻辑 2.光敏控制蜂鸣器 一.硬件 光线越强,光敏电阻的阻值越小 温度越高,热敏电阻的阻值就越小 红外光线越强,红外接收管的阻值就…

harmony os系统

因为实验室配的是Windows电脑,最近在搜索marginnote有没有windows的版本,不然好多功能相似的软件在使用不能信息同步是挺麻烦的。搜索结果当然还是没有对应版本。那我退而求其次,看看怎么在Windows上使用marginnote,结果大家意见基…

Android super.img解包和打包指南(含工具下载lpunpack、lpmake、lpdump)

本文所有命令均需要在linux 上执行 一、解包 1、将Android sparse image格式的super.img转成二进制文件 $ sudo apt install android-sdk-libsparse-utils $ simg2img super.img super.img.bin 2、下载工具lpunpack 和lpmake、lpdump 以及其依赖库 下载地址:https://downl…