Aerospike保证不了一致性

介绍

Aerospike虽然号称支持事务,但是并不能满足事务的一致性。对于内存+持久化的模式,当事务提交后,事务操作的记录值并没有刷到磁盘上,只是将其存到了swb的缓存中。这个缓存由一个后台线程进行刷写。如果事务提交后,此时所有的值都是看得到的;而其值没有刷到磁盘上,此时宕机重启后是会丢失记录的。至于丢失多少事务的记录,就要看没有刷到磁盘的swb有多少,如果有很多事务的swb没有刷到磁盘上,那么将会有很多事务的记录丢失。感觉这是Aerospike社区版的一个大坑。对于一致性要求特别严的业务是没法使用的。

代码分析

以insert操作为例。一个insert的事务的调用流程:

write_master->write_master_dim->as_storage_record_write
->as_storage_record_write_ssd->ssd_write->ssd_write_bins

其中,ssd_write_bins是将记录值存放到swb的函数。

ssd_write_bins(as_storage_rd *rd)
{
	//计算记录的大小
	uint32_t write_size = ssd_write_calculate_size(rd);
	//向swb写入时,需要加锁保证只有一个线程进行访问往里写
	pthread_mutex_lock(&ssd->write_lock);
	/*
	1、记录值写入到ssd->current_swb中。
	2、如果改值是NULL,需要通过swb_get函数获取一个
	3、从ssd->swb_free_q队列获取,如果该队列空,那么malloc一个swb
	*/
	ssd_write_buf *swb = ssd->current_swb;
	if (! swb) {
		swb = swb_get(ssd);
		ssd->current_swb = swb;
		if (! swb) {
			pthread_mutex_unlock(&ssd->write_lock);
			return -AS_PROTO_RESULT_FAIL_OUT_OF_SPACE;
		}
	}
	/*
	如果记录的大小大于current_swb的剩余空间:
	  1、将其剩余空间置0,并放到swb_write_q队列中等待刷写
	  2、从新获取一个新的swb,获取方法同上,作为新的current_swb
	  3、将记录放到current_swb缓存中
	  4、注意这里ssd->write_block_size的值是1M,即一个swb大小是1M;一个rd最大只能是1M
	*/
	if (write_size > ssd->write_block_size - swb->pos) {
		if (ssd->write_block_size != swb->pos) {
			memset(&swb->buf[swb->pos], 0, ssd->write_block_size - swb->pos);
		}

		// Enqueue the buffer, to be flushed to device.
		cf_queue_push(ssd->swb_write_q, &swb);
		cf_atomic64_incr(&ssd->n_wblock_writes);

		// Get the new buffer.
		swb = swb_get(ssd);
		ssd->current_swb = swb;

		if (! swb) {
			cf_warning(AS_DRV_SSD, "write bins: couldn't get swb");
			pthread_mutex_unlock(&ssd->write_lock);
			return -AS_PROTO_RESULT_FAIL_OUT_OF_SPACE;
		}
	}
	uint32_t swb_pos = swb->pos;

	swb->pos += write_size;
	cf_atomic32_incr(&swb->n_writers);

	pthread_mutex_unlock(&ssd->write_lock);
	...将rd值放到swb中
}
swb刷写后台线程:

as_storage_namespace_init_ssd->ssd_start_write_worker_threads->
pthread_create(&ssd->write_worker_thread[j], 0, ssd_write_worker,(void*)ssd);

ssd_write_worker:
	while (ssd->running) {
		ssd_write_buf *swb;

		if (CF_QUEUE_OK != cf_queue_pop(ssd->swb_write_q, &swb, 100)) {
			continue;
		}
		ssd_flush_swb(ssd, swb);
	}

可以看到后台线程作为一个死循环不断从swb_write_q队列中取脏的swb进行刷写。

另外,这个刷写函数中间没有停歇,会造成CPU一直很忙。

总结

对于一致性要求高的业务,需要开发相应功能来满足这个需求。这是社区版的一个缺陷。对于企业版怎么样呢?如果Aerospike不向MySQL等开源关系型数据库一样开放出更多的功能和解决的bug,感觉他很难流行起来。说起来bug,Aerospike也没有一个供使用者提bug的页面;当用户发现bug时不能提交给社区只能自己解决;这也是Aerospike不能尽快流行起来的一个原因吧。

相关文章
相关标签/搜索