在当今快速发展的信息技术领域,数据存储的需求日益增长,这促使寻求更高效、更灵活的存储解决方案。TmStorage就是这样一种创新的存储系统,它不仅能够存储各种类型的信息,而且具有扁平化的结构,使得数据管理更加直观和高效。本文将详细介绍TmStorage的设计原理、实现方式以及其潜在的应用场景。
TmStorage最初被设计为一种文件系统,但随着功能的不断扩展,它逐渐演变成了一种通用的存储系统。与传统的文件系统不同,TmStorage采用了扁平化的结构,这意味着所有的数据流都存储在一个文件中,而不是分散在多个文件夹和子文件夹中。这种设计使得TmStorage能够轻松地扩展,以适应不断增长的数据量。
TmStorage的核心功能包括:
TmStorage提供了创建、打开和删除数据流的方法。以下是一个示例,展示了如何在TmStorage中保存一张图片:
Image image = Image.FromFile("c:\\image.png");
Storage storage = new Storage("c:\\images.storage", "c:\\images.storagelog");
Guid streamId = Guid.NewGuid();
storage.StartTransaction();
try
{
Stream stream = storage.CreateStream(streamId);
image.Save(stream, ImageFormat.Png);
stream.Close();
storage.CommitTransaction();
}
catch
{
storage.RollbackTransaction();
}
TmStorage是一个开源项目,采用MIT许可证,这意味着任何人都可以自由地使用它,无论是商业用途还是非商业用途。项目源代码可以在SourceForge和GitHub上找到:
TmStorage使用一个主文件来存储所有的数据流。主文件被划分为可变长度的段,每个段只能被一个数据流拥有。每个数据流可以由零个或多个段组成,这些段被链式连接在一起。标记空闲空间的段也被链式连接在一起,形成一个称为空闲空间流的流。
每个段的开始处都写有段元数据,包含以下信息:
为了减少碎片化,段的大小总是块大小的倍数,块大小固定为512字节。
当创建一个新的空存储时,会创建一个空闲空间流,它由一个段组成,占据了主文件中所有可用的虚拟空间(2^64字节)。主文件的实际大小永远不会像空闲空间流那么大,因为空闲空间流不包含任何数据,它的大小只是虚拟的。
在为数据流分配或回收空间时,只能对段执行两种操作:分割或合并。当数据流扩大时,会从空闲空间流中取出整个段或分割段,并添加到数据流的段链中。
当数据流缩小时,过程相同,只是数据流和空闲空间流的位置互换。当段被添加到段链中时,所有相邻的段会被合并成更大的段,以防止过度分割。
所有数据流的元数据都存储在数据流表中。数据流表本身存储在一个数据流中,该数据流具有硬编码的数据流ID和硬编码的第一个段位置,因此在打开存储时,即使数据流表尚未加载,也可以找到它。
数据流元数据包含以下信息:
数据流ID的类型是GUID,原因之一是,无论何时何地创建新的数据流ID(例如,使用Guid.CreateNew()),都可以独立于TmStorage创建。因此,即使在实际使用之前很久就创建了数据流ID,也可以确保其唯一性。如果数据流ID是整数,那么就需要一个带有存储的MaxId值的数据流ID生成器。
初始化长度是包含有效数据的数据流长度。这用于优化。当数据流大小扩大时,新分配的空间包含随机(或残留)数据,因为字节不会被初始化为0。如果初始化为0,那么写入数据流的操作就会执行两次,从而降低性能。初始化长度总是小于或等于数据流长度,并且在扩大数据流时不会改变,但当写入数据流时会增长。所有在初始化长度以上(直到数据流长度)读取的字节都会自动设置为0,而不需要实际从数据流中读取。
标签是用于存储一些自定义信息的地方,例如数据流中的数据类型。
TmStorage支持完整的事务处理。它们是在主文件级别实现的。在事务期间,每次写入主文件时,TmStorage都会将即将被覆盖的数据复制到事务日志文件中。TmStorage还会记录哪些部分已经被备份,以避免重复备份。事务日志文件是一个单独的文件,位于主文件旁边,当事务提交时会被清除。
如果在抛出异常时,可以回滚事务。如果计算机在事务期间崩溃,下次打开存储时,存储会识别出事务没有完成并进行回滚。
TmStorage目前并不是用于高性能多用户数据库的,而更多地用作各种应用程序的数据存储,其中性能并不是关键因素。
即使在填充了一百万条数据流之后,TmStorage的性能仍然非常好。即使在填充了三百万条数据流之后,它仍然运行良好。数据流表完全加载在内存中,因此访问速度非常快。
缺少的一个特性是缓存层。想法是在内存中缓存主文件的块以加快读取速度。如果存储不太大,所有数据都可以被缓存。
还想要实现快照功能。想法是能够对当前存储进行快照,以便所有对它的更改只写入快照。最后,可以选择将更改与主文件合并,或者丢弃它们。这在测试写入存储的软件时非常有用,因为每次开始测试时,不必每次都对存储主文件进行完整备份。