cassandra

两种方式:

Cassandra-ArchitectureCommitLog

Cassandra持久化-Durability

一种是配置commitlog_sync为periodic,定期模式;另外一种是batch,

默认(Cassandra1.2.19/3.0.0)为periodic,定期10000ms

#commitlog_sync: batch
#commitlog_sync_batch_window_in_ms: 50
commitlog_sync: periodic
commitlog_sync_period_in_ms: 10000

这里如果是periodic模式潜在丢数据的风险,来看看两种实现方式,大致调用顺序

StorageProxy. ->WritePerformer.apply()->counterWriteTask()/sendToHintedEndpoints()->((CounterMutation/mutation).apply()->Mutation.apply()->Keyspace.apply()->CommitLog.instance.add(mutation),主要看CommitLog.instance.add(mutation)

CommitLog.instance.add(mutation)

public ReplayPosition add(Mutation mutation)
{
assert mutation != null; long size = Mutation.serializer.serializedSize(mutation, MessagingService.current_version); long totalSize = size + ENTRY_OVERHEAD_SIZE;
if (totalSize > MAX_MUTATION_SIZE)
{
throw new IllegalArgumentException(String.format("Mutation of %s bytes is too large for the maxiumum size of %s",
totalSize, MAX_MUTATION_SIZE));
} Allocation alloc = allocator.allocate(mutation, (int) totalSize);
try
{
ICRC32 checksum = CRC32Factory.instance.create();
final ByteBuffer buffer = alloc.getBuffer();
BufferedDataOutputStreamPlus dos = new DataOutputBufferFixed(buffer); // checksummed length
dos.writeInt((int) size);
checksum.update(buffer, buffer.position() - 4, 4);
buffer.putInt(checksum.getCrc()); int start = buffer.position();
// checksummed mutation
Mutation.serializer.serialize(mutation, dos, MessagingService.current_version);
checksum.update(buffer, start, (int) size);
buffer.putInt(checksum.getCrc());
}
catch (IOException e)
{
throw new FSWriteError(e, alloc.getSegment().getPath());
}
finally
{
alloc.markWritten();
}
executor.finishWriteFor(alloc);
return alloc.getReplayPosition();
}

这里主要写buffer,没有刷盘,这时会有两种方式,就是之前说的periodic与batch,主要看 executor.finishWriteFor(alloc),起里边调用了maybeWaitForSync(),是一个抽像的,在BatchCommitLogService与PeriodicCommitLogService中实现

public void finishWriteFor(Allocation alloc)
{
maybeWaitForSync(alloc);
written.incrementAndGet();
}
protected abstract void maybeWaitForSync(Allocation alloc);

BatchCommitLogService中实现

protected void maybeWaitForSync(CommitLogSegment.Allocation alloc)
{
// wait until record has been safely persisted to disk
pending.incrementAndGet();
alloc.awaitDiskSync(commitLog.metrics.waitingOnCommit);
pending.decrementAndGet();
}
void waitForSync(int position, Timer waitingOnCommit)
{
while (lastSyncedOffset < position)
{
WaitQueue.Signal signal = waitingOnCommit != null ?
syncComplete.register(waitingOnCommit.time()) :
syncComplete.register();
if (lastSyncedOffset < position)
signal.awaitUninterruptibly();
else
signal.cancel();
}
}

这里面如果lastSyncedOffset < position是会一直等待的,知道lastSyncedOffset>=position,即当前alloc对应的buffer已被flush

PeriodicCommitLogService中实现,这里的关键是waitForSyncToCatchUp()

protected void maybeWaitForSync(CommitLogSegment.Allocation alloc)
{
if (waitForSyncToCatchUp(Long.MAX_VALUE))
{
// wait until periodic sync() catches up with its schedule
long started = System.currentTimeMillis();
pending.incrementAndGet();
while (waitForSyncToCatchUp(started))
{
WaitQueue.Signal signal = syncComplete.register(commitLog.metrics.waitingOnCommit.time());
if (waitForSyncToCatchUp(started))
signal.awaitUninterruptibly();
else
signal.cancel();
}
pending.decrementAndGet();
}
}

waitForSyncToCatchUp()

private boolean waitForSyncToCatchUp(long started)
{
return started > lastSyncedAt + blockWhenSyncLagsMillis;
}

这里的blockWhenSyncLagsMillis是1.5倍的commitlog_sync_period_in_ms

blockWhenSyncLagsMillis = (int) (DatabaseDescriptor.getCommitLogSyncPeriod() * 1.5);

为什么是1.5倍呢,我的理解是假设flush刷盘的时间是0.5个commitlog_sync_period,但是这个其实是不一定的,可能大于0.5,可能小于0.5,这里就潜在数据丢失了,假设这个确实flush一次不止0.5个commitlog_sync_period,那写完的数据其实是不确定一定刷盘了的。

具体的flush代码,位于AbstractCommitLogService中的start()方法中

long syncStarted = System.currentTimeMillis();
commitLog.sync(shutdown);
lastSyncedAt = syncStarted;
syncComplete.signalAll();

commitLog.sync()->segment.sync()->write(startMarker, sectionEnd),write在CompressedSegment与MemoryMappedSegment实现,最终都是调用的channel.force()

cassandra写数据CommitLog的更多相关文章

  1. cassandra 如何写数据以及放置副本

    application发送数据到server application 发送请求到server 根据设置的load balance 规则从cluster中挑选一个coordinator,一般使用轮询即可 ...

  2. Cassandra 的数据存储结构——本质是SortedMap<RowKey, SortedMap<ColumnKey, ColumnValue>>

    Cassandra 的数据存储结构 Cassandra 的数据模型是基于列族(Column Family)的四维或五维模型.它借鉴了 Amazon 的 Dynamo 和 Google's BigTab ...

  3. Android开发学习---如何写数据到外部存储设备(sd卡),Environment.getExternalStorageDirectory,怎么获取sd卡的大小?

    本文主要介绍如何写数据到sd卡,这里主要到的技术是Environment中的方法. 1. 2.实现代码: /datasave/src/com/amos/datasave/savePasswordSer ...

  4. python 使用openpyxl来写数据到excel表格

    使用openpyxl写execl确实很方便.我先介绍用到的相关模块与函数 Workbook:工作簿模块,在内存创建一个工作簿. ExcelWriter:使用它向exel中写数据. get_column ...

  5. 串行通讯之.NET SerialPort异步写数据

    目录 第1章说明    2 1 为什么需要异步写数据?    2 2 异步写数据的代码    2 3 源代码    4 第1章说明 1 为什么需要异步写数据? 如下图所示,以波特率300打开一个串口. ...

  6. mysql 写数据操作几次硬盘?

    mysql 写数据步骤: 1:写入操作事物日志,持久化操作日志到磁盘,并且只是写在磁盘上一小块区域内的顺序io,不需要像随机io一样 在磁盘多个地方移动磁头 2:内存中事物日志持久化以后  ,写入的数 ...

  7. Hbase写数据,存数据,读数据的详细过程

    Client写入 -> 存入MemStore,一直到MemStore满 -> Flush成一个StoreFile,直至增长到一定阈值 -> 出发Compact合并操作 -> 多 ...

  8. USB系列之四:向U盘上写数据

    在<USB系列之三>中,我们实现了一系列的SCSI命令,在这个系列中,我们要实现向U盘上写扇区的命令,所以,本文相对比较容易,更多地是给出一个实现的源程序. 在<USB系列之三> ...

  9. Linux启动kettle及linux和windows中kettle往hdfs中写数据(3)

    在xmanager中的xshell运行进入图形化界面 sh spoon.sh 新建一个job

随机推荐

  1. elastic search使用总结

    1. elasticsearch安装 官方下载地址:https://www.elastic.co/downloads/elasticsearch 解压文件 elasticsearch-2.4.0.zi ...

  2. 导出Excel通用工具类

    导出Excel的两种方法: 一,POI 导入poi包 poi-3.11-beta3-20141111.jar /** * */ package com.car.ots.mpckp.utils; imp ...

  3. windows7 gvim 配置(好用)

    http://blog.csdn.net/anders_zhuo/article/details/8949003

  4. PYTHON lambda表达式

    lambda相当于def定义函数     一一对应

  5. empty和isset函数详解

    1.empty函数 用途:检测变量是否为空 若变量不存在则返回 TRUE 若变量存在且其值为"".0."0".NULL..FALSE.array().var $ ...

  6. select2 demo

    https://select2.github.io/examples.html 一大堆的坑: 1. 不同版本之间貌似不兼容,对应版本看对应的文档. 2. 4.0.3版本: 1). 自定义渲染的opti ...

  7. 《转载》Spring MVC之@RequestParam @RequestBody @RequestHeader 等详解

    引言: 接上一篇文章,对@RequestMapping进行地址映射讲解之后,该篇主要讲解request 数据到handler method 参数数据的绑定所用到的注解和什么情形下使用: 简介: han ...

  8. Mysql 存储引擎中InnoDB与Myisam的主要区别

    一直以为我spring事物没有配置好,结果发现是mysql的表本身设置成了Myisam 引擎.改成innodb就支持事物了. 1, 事务处理 innodb 支持事务功能,myisam 不支持. Myi ...

  9. win10进入安全模式的方法(F8不管用/开不开机)

    win10默认不能进入安全模式,这时候开机黑屏怎么办?下面介绍强制进入安全模式的方法 1. 关机情况下,按开机键开机,等到出现徽标(下图),这时候长按开机键强制关机. 2. 再次开机,出现徽标,再次强 ...

  10. Mosquitto搭建Android推送服务(一)MQTT简介

    总体概要: MQTT系列文章分为4部分 1.MQTT简介 2.mosquitto服务器搭建 3.编写Mosquitto的可视化工具 4.使用Mosquitto完成Android推送服务 文章钢要: 对 ...