美文网首页我爱编程
小白谈分布式数据库设计1——文件系统设计

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

作者: 谜碌小孩 | 来源:发表于2018-03-05 11:13 被阅读0次

设计一款分布式数据库

随着不断变化的需求和不断增加的数据量,越来越多的新型数据库,如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();
        }
    }
}

相关文章

网友评论

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

    本文链接:https://www.haomeiwen.com/subject/heicfftx.html