数据恢复之commitlog

cassandra作为海量数据处理的DB,为了提升性能,则先将数据写入到内存表memtable中,然后当memtable达到一定容量条件时,再将memtable中数据持久化到硬盘上。但是如果系统宕机,或者重启,那么内存的数据就会丢失,所以需要一个保护功能——commitlog,来恢复原来存在于内存表中的数据。


1、commitlog触发的条件

条件1:CF所在的Keyspace的属性durableWrites,如果durableWrites为true,则写入数据的时候,同时会写commitlog。

条件2:写入的数据序列化以后写入commitlog文件中的长度(序列化长度+4(长度)+8(校验码的长度)+8(校验码))必须小于等于commitlog文件的大小(cassandra.yaml文件中的配置项:commitlog_segment_size_in_mb:32)。才会写commitlog,否者告警,但是不写。

 long totalSize = RowMutation.serializer.serializedSize(rm, MessagingService.current_version) + CommitLogSegment.ENTRY_OVERHEAD_SIZE;
        if (totalSize > DatabaseDescriptor.getCommitLogSegmentSize())
        {
            logger.warn("Skipping commitlog append of extremely large mutation ({} bytes)", totalSize);
            return;
        }


2、commitlog记录数据的流程

2.1、执行器

如果一旦需要写commitlog,cassandra也不会每次每条数据都进行持久化到磁盘commitlog文件中,因为这样会严重影响数据写入的性能。所以cassandra会将每次数据提交给另外一个执行器进行数据的持久化。

执行器有两种。分别为:BatchCommitLogExecutorService和PeriodicCommitLogExecutorService,是有cassandra.yaml文件中配置项commitlog_sync来决定的。

执行器1:BatchCommitLogExecutorService

配置项:

commitlog_sync: batch

commitlog_sync_batch_window_in_ms: 50

执行器BatchCommitLogExecutorService,将50ms内的数据作为一个批次进行持久化到硬盘上去。


执行器1:PeriodicCommitLogExecutorService

配置项:

commitlog_sync: periodic
commitlog_sync_period_in_ms: 10000

有commitlog的写入的任务,则将数据直接写入到CommitLogSegment,但是没10s(commitlog_sync_period_in_ms)中才会将CommitLogSegment中的数据持久化到硬盘中。


2.2分配器CommitLogAllocator

需要写入commitlog记录的数据,首先会写入到CommitlogSegment中,而一个CommitlogSegment就相当于commitlog文件的内存映射一样,记录着每个CF对应写入commitlog文件的记录的起始位置,该信息存放在属性private final HashMap cfLastWrite = new HashMap();这个消息便于表数据flush的时候生成写入的最后位置


2.3、commitlog数据的序列化

数据写入commitlog中的序列化格式和sstable中的格式是一致的,但是多了一重校验数据完整性的验证码。使用的是CRC32校验。

Checksum checksum = new PureJavaCrc32();
        byte[] serializedRow = FBUtilities.serialize(rowMutation, RowMutation.serializer, MessagingService.current_version);

        checksum.update(serializedRow.length);
        buffer.putInt(serializedRow.length);
        buffer.putLong(checksum.getValue());

        buffer.put(serializedRow);
        checksum.update(serializedRow, 0, serializedRow.length);
        buffer.putLong(checksum.getValue());


3、commitlog恢复数据的流程





你可能感兴趣的:(数据恢复之commitlog)