小白谈分布式数据库设计1——文件系统设计

设计一款分布式数据库

随着不断变化的需求和不断增加的数据量,越来越多的新型数据库,如hbase、mongodb、cassandra等,逐渐在一些领域取代了传统的关系型数据库,收到的越来越广泛的关注。

单机数据库设计

对于任意一款软件,最重要的是它的设计思想和解决的问题.如程序语言一样,是面向对象,还是面向过程?是性能至上,还是开发效率优先?任何一种语言或软件,如果能解决一个甚至多个核心痛点,即使在其他方面有一些短板,也必然会受到追捧.除了设计思想,软件的架构也是十分重要的.初始架构的设计往往决定了它以后的发展.可扩展性,功能模块的添加和适配,性能的优化等等都会受到架构的影响,重构总是要付出很大代价的,所以核心模块和接口的设计,一定要谨慎决策.核心架构决定了一款软件的起点,设计思想决定了一款软件的终点.
如何设计一款可用的分布式数据库?首先,我们要简化思路,先设计在单机可上用的存储引擎和数据结构,然后再考虑分布式数据库所需要的譬如横向扩展,一致性,数据备份等等一系列问题.现在,我们先看看单机运行的数据库应该有哪些模块.为了快速搭起架子,我们先抛开性能和复杂的逻辑,一切以最简单的逻辑来完成。
首先,是核心模块的设计.预先设计的模块主要有文件系统(FileSystem),IO(文件读写),NET(RPC),读写缓存cache(Memtable),内存管理,磁盘存储(SSTable,类似HBase的storefile),日志系统(commitlog),服务(service)。
单机扩展到集群后,会增加一致性,分区路由,数据传输等模块,单机下的一些模块也会有所变化。

文件系统

首先,我们设计文件系统接口IFileSystem和IFile。IFileSystem只是为了包装不同的文件系统(为后续接入HDFS等拓展做准备)。默认为操作系统的文件系统。IFile主要是为了包装不同的文件。
IFileSystem我们暂且不去管它,IFile接口如下,Mode是一个Enum,只有READ和WRITE。

public interface IFile<T> extends Closeable{
    boolean delete();
    boolean exists();
    boolean isDirectory();
    T open(Mode mode) throws FileNotFoundException;
    String getPath();
    List<IFile> listFiles();

    enum Mode {
        READ, WRITE
    }
}

DefaultFile,仅仅只是包装了File,并且是线程不安全的.这里有很多问题,我们暂且不管,先实现大体的架构

public class DefaultFile implements IFile<FileChannel> {
    private File file;
    private FileInputStream fileInputStream;
    private FileOutputStream fileOutputStream;

    public DefaultFile(File file) {
        this.file = file;
    }

    public DefaultFile(String path) {
        this.file = new File(path);
    }

    @Override
    public boolean delete() {
        return file.delete();
    }

    @Override
    public boolean exists() {
        return file.exists();
    }

    @Override
    public boolean isDirectory() {
        return file.isDirectory();
    }

    @Override
    public FileChannel open(Mode mode) throws FileNotFoundException {
        FileChannel fileChannel = null;
        synchronized (this) {
            switch (mode) {
                case READ:
                    if (fileInputStream == null) {
                        fileInputStream = new FileInputStream(file);
                    }
                    fileChannel = fileInputStream.getChannel();
                    break;
                case WRITE:
                    if (fileOutputStream == null) {
                        fileOutputStream = new FileOutputStream(file);
                    }
                    fileChannel = fileOutputStream.getChannel();
                    break;
            }
        }
        return fileChannel;
    }

    @Override
    public String getPath() {
        return file.getAbsolutePath();
    }

    @Override
    public List<IFile> listFiles() {
        File[] files = file.listFiles();
        if(files == null) return new ArrayList<>(0);
        List<IFile> result = new ArrayList<>(files.length);
        for(File file:files){
            IFile iFile = new DefaultFile(file);
            result.add(iFile);
        }
        return result;
    }

    @Override
    public void close() throws IOException {
        if(fileInputStream != null){
            fileInputStream.close();
        }
        if(fileOutputStream != null){
            fileOutputStream.flush();
            fileOutputStream.close();
        }
    }
}

文件IO

对于文件的读写,我们仅以BytBuffer的形式来进行。这里预先设计两个接口,

public interface IFileReader {
    byte[] read(long start, long size) throws IOException;
}
public interface IFileWriter {
    void write(ByteBuffer buffer) throws IOException;
}

先提供简单的实现方式,ByteBufferUtils为ByteBuffer的工具类,主要用于ByteBuffer的读写

public class DefaultFileReader implements IFileReader {
    private IFile<FileChannel> file;

    public DefaultFileReader(IFile<FileChannel> file) {
        this.file = file;
    }

    @Override
    public byte[] read(long start, long size) throws IOException {
        FileChannel fileChannel = file.open(IFile.Mode.READ);
//        FileLock lock = fileChannel.tryLock();
        try {
            MappedByteBuffer byteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, start, size);
            byteBuffer.flip();
            byte[] result = ByteBufferUtils.readBuffer(byteBuffer);
            byteBuffer.clear();
            ByteBufferUtils.release(byteBuffer);
            return result;
        } finally {
//            lock.release();
            fileChannel.close();
        }
    }
}
public class DefaultFileWriter implements IFileWriter {
    private IFile<FileChannel> iFile;

    public DefaultFileWriter(IFile<FileChannel> iFile) {
        this.iFile = iFile;
    }

    @Override
    public void write(ByteBuffer buffer) throws IOException {
        FileChannel fileChannel = iFile.open(IFile.Mode.WRITE);
        buffer.flip();
        FileLock lock = fileChannel.tryLock();
        try {
            fileChannel.write(buffer);
            buffer.clear();
        } finally {
            lock.release();
            fileChannel.close();
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,757评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,478评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,540评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,593评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,903评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,329评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,659评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,383评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,055评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,337评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,864评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,227评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,820评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,999评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,750评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,365评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,260评论 2 258

推荐阅读更多精彩内容

  • 本文转载自http://geek.csdn.net/news/detail/112672 WeTest导读 我们常...
    shineegirl阅读 1,532评论 0 26
  • 1. 概述 本文以淘宝作为例子,介绍从一百个并发到千万级并发情况下服务端的架构的演进过程,同时列举出每个演进阶段会...
    小亮__阅读 252评论 0 0
  • 爱你 有弹性的皮肤 光滑 有光泽 是荔枝白色果肉的饱满 如果夏季的热风包裹 如果38度的光线穿透 它的毛孔会战栗 ...
    薄薄的草阅读 287评论 0 1
  • 1 时隔五年,白然再次登上紫清山顶。 金黄色的梧桐叶铺满了一地,落寞的亦如白然的心情。他终究还是没有来,终究还是不...
    九黎呀阅读 1,158评论 5 19
  • 深夜,外面的狗突然大叫了起来,又同时伴随着狗链子在地上拖拉的声音,我跟着爷爷打着照明效果不是很好的手电筒,...
    浩浩小白阅读 272评论 0 0