最近在忙作业的事,原本每天正午都要午睡的,我媳妇 都让我冷静点,但我冷静不了,知道没什么用,可是我极力就好,让更多人看到

从前几天就看到的 《僧丫》的实名告发助学金名额被挤占,这几天一直在重视,直到11月2号清晨, 《四川观察》 第一个官媒帮忙发视频。

我也是一个单亲家庭,我听他自己的视频的时候 认真的听,不争气的说(我哭了),能感觉到他的无法,特别那句 奶奶和他说 家里真的没钱了,咱们对这种事或许早就见过 或许 听过,可是一般都是不管不顾,由于没有必要,但能感觉到 他是遇到了特别的难处

我其时家里亲属和我孤儿寡母 的打官司,要我家房子,打了4年,从12岁打到16岁,原本能赢的,前面还老赢,后面咱们没钱请律师了,终审 判给了他们,4家,一家8w块,(16年前),这个社会就这样,我早看透了,希望大家去b站,或许抖音 帮顶下

僧丫 18岁的户主

建档立卡都评不上,操

假如占用了的资源,抱歉

气愤的点

b站在《僧丫》视频出来几个小时 就删除了

我看到了,然后后面就看不了了

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战

《僧丫》给出了依据,还有人说风凉话

我相信这绝不是仅有的一件,我其时的大学导员便是 奖学金,助学金都是内定的,仅仅人家预备了一堆理由,让你找不到把柄,明眼人谁不知道怎样回事,我相信

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战

今日再看一篇文章的时候,看到一句话

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战

的确我也感觉有点 纯理论了,我给补充点代码

问题列表

  1. rocketmq 怎样做的存储模块
  2. 操作体系怎样做到的“依照空间占用份额”、“时刻周期扫描”

本节细节

  1. 怎样判别 操作体系PageCache繁忙
  2. 做一个sdk,让咱们能直接使用

布景

我是一枚大专非计算机专业的 java程序员,读写文件 我或许第一印象是File的工具类,比方

long startTime = System.currentTimeMillis();
        MultipartFile multipartFile = req.getFile();
        PDDocument document;
        String doc = "";
        String originalFilename = "";
        String prefixStr;
        File file;
        try {
            originalFilename = multipartFile.getOriginalFilename();
            String[] filename = originalFilename.split(".");
            prefixStr = String.join(".", Arrays.copyOfRange(filename, 0, filename.length - 1));
            file = File.createTempFile(VerificationCodeGenerator.generateCode(6), "."   filename[filename.length-1]);
            multipartFile.transferTo(file);
            long startTime1 = System.currentTimeMillis();
            document = PDDocument.load(file);
            long endTime1 = System.currentTimeMillis();
            System.out.println("读取pdf 花费的时刻:"   (endTime1 - startTime1));
            PDFTextStripper pdfStripper = new PDFTextStripper();
            doc = pdfStripper.getText(document);
            long endTime2 = System.currentTimeMillis();
            System.out.println("读取doc内容 花费的时刻:"   (endTime2 - startTime1));
//            file.deleteOnExit();
            document.close();
        } catch (IOException e) {
            log.error(e.getMessage());
            return null;
        }

大约读一个100页的pdf 耗时

读取pdf 花费的时刻:104
读取doc内容 花费的时刻:264
读取pdf 花费的时刻:127
读取doc内容 花费的时刻:486
读取pdf 花费的时刻:64
读取doc内容 花费的时刻:364
读取pdf 花费的时刻:98
读取doc内容 花费的时刻:287

有没有办法优化下呢

分两种,由于pdf 是特别的文件,FileChannal 读取不了pdf内容,一般都是操作的txt。

  1. 基础中心件的高功能读写
  2. 事务中 读取pdf / docx 等文件的读写

今日这篇 咱们先说 基础中心的高功能读写

  1. 内存读写的功率高于硬盘读写
  2. 批量读写的功率高于单条读写
  3. 次序读写的功率高于随机读写
  4. 数据仿制次数越多,功率越低

详细说说

进步写入操作的功能

写入功能的进步首要有缓存写、批量写、次序写三个思路,这里对比来讲。

写入内存 就回来肯定是最快的,可是还要确保高功能的一起,不丢掉数据

缓存写 与批量写

在计算机理论基础中,计算机多级存储模型的层级越高,代表速度越快(一起容量也越小,价格也越贵),也便是说写入速度从快到慢分别是:寄存器 > 缓存 > 主存 > 本地存储 > 远程存储。

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战

写入优化的首要思路之一是:将数据写入到速度更快的内存中,等积累了一批数据,再批量刷到硬盘中。

平时咱们在一些技术文章看到的“数据先写入 PageCache,再批量刷到硬盘”,说的便是这个思路。PageCache 指操作体系的页缓存,简单了解便是内存,经过缓存读写数据能够避免直接对硬盘进行操作,从而进步功能。

把缓存数据刷回到硬盘,一般有“依照空间占用份额”、“时刻周期扫描”和“手动强制改写”三种战略。操作体系内核供给了前两种处理战略,不需要应用程序感知。咱们详细了解一下。

按空间占用份额改写是指当体系内存中的“脏”数据大于某个阈值时会将数据改写到硬盘。

操作体系供给了两个装备项。

  1. “脏”数据在内存中的占比(dirty_background_ratio)
  2. “脏”数据的肯定的字节数(dirty_background_bytes)

当这两个装备超越阈值,就会触发改写操作。假如两者一起设置,则以肯定字节数为更高优先级。

按时刻周期改写是指依据装备好的时刻,周期性改写数据到硬盘。首要经过脏页存活时刻(dirty_expire_seconds) 和改写周期(dirty_writeback_centisecs)两个参数来装备。两个装备默许都是 1/100,也就说时刻距离为每秒 100 次,依据改写周期的装备周期性履行改写,改写会查看脏页的存活时刻是否超越装备的最大存活时刻,假如是则刷入硬盘。

一起,操作体系也供给了第三种方法程序手动强制改写,你能够经过体系供给的 sync()/msync()/fsync() 调用来强制改写缓存。经过操作体系的参数装备,在 Java 代码中,经过 Java.NIO 包中 FileChannel 供给的 write() 和 force() 方法,实现写缓存和强制改写缓存。代码参阅:

FileChannel channel = fin.getChannel();
file.write(buf)
file.force(true)

经过 FileChannel 供给的 write() 方法写数据时,FileChannel 把数据写入到缓存就会回来成功,然后依赖操作体系的缓存更新战略,将数据改写到硬盘。咱们也能够在代码中调用 FileChannel 供给的 force() 方法,把数据立即刷入刷盘中避免丢掉。

根本一切的音讯队列在写入时用的都是这个方案,比方 Kafka、RocketMQ、Pulsar 便是先写入缓存,然后依赖操作体系的战略改写数据到硬盘。

音讯队列一般会一起供给:是否同步刷盘、刷盘的时刻周期、刷盘的空间份额三个装备项,让事务依据需要调整自己的改写战略。从功能的角度看,异步改写肯定是功能最高的,同步改写是可靠性最高的。

rocketmq 怎样做的存储模块

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战

Broker 怎样进行的优化呢?

先把本地Rocketmq 跑起来,能够看 Rocketmq源码(一)手把手本地调试_本地测验rocketmq_Serena0814的博客-CSDN博客

首要代码在 broker中调用的store代码

@Override
public CompletableFuture<PutMessageResult> asyncPutMessage(MessageExtBrokerInner msg) {
    PutMessageStatus checkStoreStatus = this.checkStoreStatus();
    if (checkStoreStatus != PutMessageStatus.PUT_OK) {
        return CompletableFuture.completedFuture(new PutMessageResult(checkStoreStatus, null));
    }
    PutMessageStatus msgCheckStatus = this.checkMessage(msg);
    if (msgCheckStatus == PutMessageStatus.MESSAGE_ILLEGAL) {
        return CompletableFuture.completedFuture(new PutMessageResult(msgCheckStatus, null));
    }
    long beginTime = this.getSystemClock().now();
    CompletableFuture<PutMessageResult> putResultFuture = this.commitLog.asyncPutMessage(msg);
    putResultFuture.thenAccept((result) -> {
        long elapsedTime = this.getSystemClock().now() - beginTime;
        if (elapsedTime > 500) {
            log.warn("putMessage not in lock elapsed time(ms)={}, bodyLength={}", elapsedTime, msg.getBody().length);
        }
        this.storeStatsService.setPutMessageEntireTimeMax(elapsedTime);
        if (null == result || !result.isOk()) {
            this.storeStatsService.getPutMessageFailedTimes().incrementAndGet();
        }
    });
    return putResultFuture;
}

查看 Store 状况

private PutMessageStatus checkStoreStatus() {
    //本身broker 是否关闭
    if (this.shutdown) {
        log.warn("message store has shutdown, so putMessage is forbidden");
        return PutMessageStatus.SERVICE_NOT_AVAILABLE;
    }
    //假如是broker的子节点
    if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) {
        long value = this.printTimes.getAndIncrement();
        if ((value % 50000) == 0) {
            log.warn("broke role is slave, so putMessage is forbidden");
        }
        return PutMessageStatus.SERVICE_NOT_AVAILABLE;
    }
    if (!this.runningFlags.isWriteable()) {
        long value = this.printTimes.getAndIncrement();
        //% 50000 仅仅为了打印日志 找问题
        if ((value % 50000) == 0) {
            log.warn("the message store is not writable. It may be caused by one of the following reasons: "  
                "the broker's disk is full, write to logic queue error, write to index file error, etc");
        }
        return PutMessageStatus.SERVICE_NOT_AVAILABLE;
    } else {
        this.printTimes.set(0);
    }
    if (this.isOSPageCacheBusy()) {
        return PutMessageStatus.OS_PAGECACHE_BUSY;
    }
    return PutMessageStatus.PUT_OK;
}

分析上述查看broker状况代码,broker回绝写入音讯有以下几种情况:

  1. broker处于中止状况。broker在中止时,会告诉MessageStore将shutdown标识设置为true
  2. broker是slave人物
  3. broker不支持写入,或许是磁盘满了、写consumeQueue音讯队列过错或是写IndexFile过错等原因
  4. 操作体系PageCache繁忙

怎样判别 操作体系PageCache繁忙

public boolean isOSPageCacheBusy() {
    long begin = this.getCommitLog().getBeginTimeInLock();
    long diff = this.systemClock.now() - begin;
    //代码@2
    return diff < 10000000
        && diff > this.messageStoreConfig.getOsPageCacheBusyTimeOutMills();
}
  • begin 通俗的一点讲,便是将音讯写入Commitlog文件所持有锁的时刻,准确说是将音讯体追加到内存映射文件(DirectByteBuffer)或pageCache(FileChannel#map)该进程中开端持有锁的时刻戳,详细的代码请参阅:CommitLog#putMessage。
  • diff 一次音讯追加进程中持有锁的总时长,即往内存映射文件或pageCache追加一条音讯所耗时刻。

代码@2:假如一次音讯追加进程的时刻超越了Broker装备文件osPageCacheBusyTimeOutMills,则认为pageCache繁忙,osPageCacheBusyTimeOutMills默许值为1000,表明1s。

存储到store

中心便是判别音讯是否正确,然后就开端存储

result = mappedFile.appendMessage(msg, this.appendMessageCallback);

僧丫的事 + 怎样进步存储模块的功能和可靠性 代码实战