将文件分成若干等同大小的Block
,使用进行存储,每个数据最终被表示为一个int数组,存放着Block的编号,通过哈希表(并使用缓存淘汰算法)进行存储。
文件被分成若干个等同大小的Block
,若一个Block能存下该大小的数据,则直接占用一个Block;若存不下,则分为若干个Block存储(向上取整),Block可以是不连续的。
每个Block都被分为两个部分,一个部分存放当前Block的数据长度占用4 byte,另一个部分为真正存放数据的长度。由于Block的大小是,一开始就指定好的(blockSizeBytes
),所以data_length + 4 <= blockSizeBytes
。
因为写入磁盘是比较浪费性能的操作,所以可以通过相关配置来决定什么时候需要执行写入磁盘的操作。
-
DiskUsagePattern.UPDATE
&& Put执行Put操作时,并且当前缓存实例是实时更新状态,即会向磁盘中持久化缓存。
-
DiskUsagePattern.SWAP
&&dispose()
orfreeMemoryCache()
执行了销毁操作(
dispose()
)或释放内存中的缓存操作(freeMemoryCache()
)时,并且当前缓存实例是非实时更新,即会向磁盘中持久化缓存。
存在相同Key情况下,则释放旧的Block中的数据,插入新数据。
可以借助回收站(见下文,磁盘碎片利用与整理-回收站)来更好地利用磁盘空间。
-
缓存实例初始化时,根据配置文件到指定目录进行读取数据。
-
在
MemCache
中不存在该Key缓存的时候,而磁盘中存在时,则需要进行。
从哈希表中检索该索引信息,然后根据索引信息,根据Blocks列表
信息,进行相关的==数据校验==与读取。
因为file xxx.key
文件中仅仅存放一个Map实例,数据的起始偏移量则为0,数据的长度则可以通过file.length - 4
得到;根据偏移量信息,很容易还原磁盘索引信息的K-V数据。
在缓存数据的初始化之前,先通过简单的数据校验,校验数据是否被修改;根据还原之后的索引信息,我们可以容易地得到对应的缓存数据。
数据存储需要具备数据校验功能,用于检查数据文件是否损坏,是否被篡改。
BlockDiskCache
是通过直接进行读取对象的方式,看看是否能够返回一个完整的对象,若不能则表明文件内容被篡改了。
回收站,即存放已经不使用的磁盘空间Block。
磁盘碎片由主动移除缓存产生,或者由缓存淘汰算法进行淘汰产生。
在往磁盘中持久化一个缓存时,BlockDisk会优先分配那些已经分配出来的且内容为空的Block给当前缓存进行存储,这可以避免缓存文件的持续加长。
由于Block的大小是固定的大小(在一定程度上,这种排列方式已经是整齐),且若新的缓存数据大小若大于空的Block大小,数据是可以被切割的,所以BlockDisk的存储方式无需进行碎片整理。