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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024美赛B题Searching for Submersibles原创论文完整版

Searching for Submersibles搜索潜水器 2024美赛B题Searching for Submersibles原创论文(共38页)部分内容,其余见文末: 整体框架: 1.1 问题背景与问题重述 海上游轮迷你潜水艇公司(MCMS)&…

算法基础——位运算,双指针,排序,二分

目录 1.位运算 与:& 或:| 取反&#xff1a;~ 异或&#xff1a;^或者是一个圈里有个加号的图像 移位:<<或者>> 例题:二进制中1的个数 例题&#xff1a;我们需要0 ​编辑 2.排序sort 例题&#xff1a;【模板】排序&#xff08;1&#xff09; 例题&…

大坑!react+thress.js

2. UI交互界面与Canvas画布叠加 | Three.js中文网 (webgl3d.cn) // canvas画布绝对定位 renderer.domElement.style.position absolute; renderer.domElement.style.top 0px; renderer.domElement.style.left 0px; renderer.domElement.style.zIndex -1; 我按照教程设置了…

红日三打靶!!!

红日三&#xff0c;黑盒测试 环境搭建一.外网打点1.网段探测2.端口服务扫描3.目录扫描4.网站漏洞扫描5.汇总&#xff0c;找破绽6.登陆MySQL改密码 7.进入后台&#xff0c;找能写马的地方8.蚁剑连接9.disable_functions绕过1.蚁剑插件绕过2.bypass_disablefunc_via_LD_PRELOAD绕…

AutoEncoder自动编码器、VAE变分自编码器、VQVAE量子化(离散化)的自编码器

文章目录 AutoEncoder自动编码器&#xff08;一&#xff09;AutoEncoder的基本架构&#xff08;二&#xff09;AutoEncoder的概率理解&#xff08;三&#xff09;AutoEncoder的局限 VAE变分自编码器&#xff08;Variational AutoEncoder&#xff09;&#xff08;一&#xff09;…

uni-app 经验分享,从入门到离职(三)——关于 uni-app 生命周期快速了解上手

文章目录 &#x1f4cb;前言⏬关于专栏 &#x1f3af;什么是生命周期&#x1f9e9;应用生命周期&#x1f4cc; 关于 App.vue/App.uvue &#x1f9e9;页面生命周期&#x1f4cc;关于 onShow 与 onLoad 的区别 &#x1f9e9;组件生命周期 &#x1f4dd;最后 &#x1f4cb;前言 这…

uniapp 组件封装

1. uniapp 组件封装时间戳格式化为星期 1.1. components/m-week.vue <template><text>{{week}}</text> </template> <script>export default {props: {time: String},mounted(e) {this.week this.getWeek(Number(this.time))},data() {return …

挑战杯 opencv 图像识别 指纹识别 - python

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于机器视觉的指纹识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&#xff0c;适…

[python]基于opencv实现的车道线检测

【检测原理】 一、首先进行canny边缘检测&#xff0c;为获取车道线边缘做准备 二、进行ROI提取获取确切的车道线边缘&#xff08;红色线内部&#xff09; 三、利用概率霍夫变换获取直线&#xff0c;并将斜率正数和复数的线段给分割开来 四、离群值过滤&#xff0c;剔除斜率…

Java设计模式 – 四大类型

设计模式 – 四大类型 创建型模式结构型模式行为型模式J2EE模式 设计模式&#xff08;Design pattern&#xff09;是重构解决方案 根据书Design Patterns – Elements of Reusable Object-Oriented Software&#xff08;中文译名&#xff1a;设计模式 – 可复用的面向对象软件元…

lava学习-接口

接口-Interface 1.什么是接口&#xff1f; 例&#xff1a;构造器&#xff0c;代码块在接口中统统没有&#xff0c;也不能创建对象 构造器的使用-----实现类 例&#xff1a;下图中的B类就是一个 实现类 2.接口的好处 继承只能单继承&#xff0c;而接口可以弥补类单继承的不足&am…

【蓝桥杯】环形链表的约瑟夫问题

目录 题目描述&#xff1a; 输入描述&#xff1a; 输出描述&#xff1a; 示例1 解法一&#xff08;C&#xff09;&#xff1a; 解法二&#xff08;Cpp&#xff09;&#xff1a; 正文开始&#xff1a; 题目描述&#xff1a; 据说著名犹太历史学家 Josephus 有过以下故事&a…

作业2.3

一&#xff0e;选择题 1、适宜采用inline定义函数情况是&#xff08;C&#xff09; A. 函数体含有循环语句 B. 函数体含有递归语句‘、考科一 ’ C. 函数代码少、频繁调用 D. 函数代码多、不常调用 2、假定一个函数为A(int i4, int j0) {;}, 则执行“A (1);”语句后&…

有趣的CSS - css loading动画

Loading动画 整体效果核心代码html 代码&#xff1a;css 部分代码&#xff1a; 完整代码如下html 页面&#xff1a;css 样式&#xff1a;页面渲染效果&#xff1a; 整体效果 这个 Loading 效果主要用 css3 的 animation 属性配合 border 属性来实现的。 可以用作在下拉列表 Loa…

(bean配置类的注解开发)学习Spring的第十三天

bean配置类的注解开发 问题提出 用类充当配置文件 applicationcontext.xml : Configuration注解标识此类为配置类,替代原有xml文件 看原配置文件applicationcontext.xml代码 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http:/…

微信小程序(三十二)本地异步储存API

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.同步和异步API的使用区别 2.异步API的缺陷 源码&#xff1a; index.wxml <!-- 列表渲染基础写法&#xff0c;不明白的看上一篇 --> <view class"students"><view class"item&q…

使用MATLAB驱动USRP-N320实现OFDM自收自发

文章目录 前言一、收发代码二、截取一帧 OFDM三、执行主函数四、运行结果五、资源自取 前言 本文作为实验结果记录及测试&#xff0c;方便后面回顾所做的工作。本文基于一台电脑和一台 USRP 设备实现了 OFDM 自发和自收功能 一、收发代码 ofdm_tx_rx_test.m 核心代码&#x…

C++迷宫游戏详解

个人主页&#xff1a;[PingdiGuo_guo] 收录专栏&#xff1a;[C干货专栏] 大家好呀&#xff0c;我是PingdiGuo_guo&#xff0c;今天我们来学习用C实现一个迷宫游戏。 目录 1.迷宫的具体步骤 1.1.迷宫的初始化 1.2.寻路算法 1.DFS算法 2.BFS算法 1.3.移动 2.总结 C迷宫游…

【js逆向】scrapy基础

目录 一, 爬虫工程化 二, scrapy简介 三, Scrapy工作流程(重点) 四, scrapy安装 4.1 pip 安装 4.2 wheel安装 五, Scrapy实例 六, 自定义数据传输结构item 七, scrapy使用小总结 一, 爬虫工程化 在之前的学习中我们已经掌握了爬虫这门技术需要的大多数的技术点, 但是我…

MAX31865读取PT100/PT1000电阻值

1、芯片介绍 MAX31865是简单易用的热敏电阻至数字输出转换器,优化用于铂电阻温度检测器(RTD)。外部电阻设置RTD灵敏度,高精度Δ- Σ ADC将RTD电阻与基准电阻之比转换为数字输出。MAX31865输入具有高达45V的过压保护,提供可配置的RTD及电缆开路、短路条件检测。 2、芯片特点…