couchbase作为新兴的NOSQL数据库,可堪使用的资料少的可怜,更别提中文资料了,基本上就是在官网的手册和论坛上查询所需资料,所以这要求有一定的英语基础,词汇量不是问题,不认识的直接百度,关键是语法和耐心要过关,我从刚接触couchbase开始天天啃英文手册也是读得烦躁不安,所以耐心十分重要。现在使用的是couchbase 2.2 community版本的,所以手册是这个:http://docs.couchbase.com/couchbase-manual-2.2/。这个手册中,Best Practices 与 Administrators Tasks是关于配置上的说明,Views and Indexs是关于构建数据关系的说明,这三个是最优先需要阅读的章节。Command-line Interface for Administration是讲解配置参数的工具,当具体要配置参数时应仔细阅读这一章节。
如果以前没有nosql的经验,那么理解couchbase的时候关键有两点:延后写入和松散存储。延后写入,顾名思义,couchbase在对数据进行增删时会先体现在内存中,而不会立刻体现在硬盘上,从内存的修改到硬盘的修改这一步骤是由couchbase自动完成,等待执行的硬盘操作会以write queue的形式排队等待执行,也正是通过这个方法,硬盘的I/O效率在write queue满之前是不会影响couchbase的吞吐效率的,而write queue的长度是可以设置的。松散存储也很好理解,在关系型数据库中,要先建库建表,最后插数据,而在couchbase中,bucket就相当于库,没有表的存在,直接就插数据了。关系型数据库依赖表来进行条件查询,couchbase一开始没有具备表功能的结构,所以是无法执行条件查询的,但是通过view则可以手动添加所需要的关系,view的设置是非常复杂的一部分,详情去manul里Views and indexs里学习。总之couchbase的一般逻辑是建bucket——>插入数据——>建立View。正是因为关系可以后天建立,才使得不必预先规划数据应具备的关系,随用随建即可。当然,对couchbase而言插入数据其实是插入json格式的文件。
接下来聊聊couchbase的内存。对于couchbase来说配置内存是很重要的环节,因为couchbase的精髓就在于依赖内存最大化降低硬盘I/O对吞吐量的负面影响。内存资源肯定远远少于硬盘资源,如果数据量小,那么全部数据都放在内存上自然是最优选择,这时候couchbase的效率也是异常高,但是数据量大的时候过多的数据就会被放在硬盘之中。当然,最终所有数据都会写入硬盘,不过有些频繁使用的数据提前放在内存中自然会提高效率。couchbase后台有个进程,专门把一定时间没有被访问的数据移出内存,这个进程的扫描时间和数据的最大无活动时间都是可以设置的。这里有个低水位的概念,也就是说当移除数据过多以至于内存中有效数据占用内存低于低水位的时候,couchbase会随机挑一些文件到内存中以达到低水位。对于所有文件couchbase都会建立一个额外的56byte的metadata,这个metadata功能之一就是表明数据状态,是否活动在内存中。同时文件的key也作为标识符和metadata一起长期活动在内存中。couchbase官方建议bucket申请的内存中,metadata和key所占用的内存不应超过一半,否则couchbase的性能会显著下降。而这个建议我也测试过,准确无误。因此一定内存所能支持的数据条数其实也就一定了,具体算一下就能估摸个大概。为了保证这个条件,显然当有效数据占用超过一定内存时就需要把超额数据移除了,这里有个概念,高水位。当有效数据内存占用超过高水位时,couchbase就会移除数据。高低水位都是可以设置的。
对于配置节点内存的问题,官方给了一个详细的计算公式,如下:
变量:
documents_num 工作集中文件总数
ID_size 文件key的平均大小
value_size 文件内容平均大小
number_of_replicas 为文件做的备份数
working_set_percentage 工作集中放置于内存中的比率
per_node_ram_quota 每个节点给bucket申请的内存大小
metadata_per_document 56Byte
headroom 固态硬盘:25% ,传统硬盘: 30%
high_water_mark 默认值为85%
公式:
no_of_copies 1 + number_of_replicas
total_metadata (documents_num) * (metadata_per_document + ID_size) * (no_of_copies)
total_dataset (documents_num) * (value_size) * (no_of_copies)
working_set total_dataset * (working_set_percentage)
Cluster RAM quota required (total_metadata + working_set) * (1 + headroom) / (high_water_mark)
number of nodes Cluster RAM quota required / per_node_ram_quota
Couchbase相比其他数据库操作起来要更为麻烦一些,尤其是操作数据上,可以说couchbase server本身为了追求效率直接就把一些工作放弃了,为此在其他数据库上简单的数据操作到这里必须要好好规划一番才行。这一次主要是简单介绍一下在Couchbase中如何进行条件查询,而理解了条件查询自然也就能明白相应的数据删改是如何操作。
首先要清楚地认识到,couchbase本身存储的数据之间是毫无关系的,如果不提前做好准备就无法进行任何条件查询,而条件查询的必要前提就是建立了正确的View。在couchbase中,一个bucket下包含多个design document,而每一个document中又包含多个View,这个结构的意义会在后面说,总之先有个概念。
View的写法还是结合manul中的实例比较方便,http://docs.couchbase.com/couchbase-manual-2.2/#writing-views,写法并不复杂,但是需要注意key的作用。这里的key就是可供我们条件查询的索引,所以根据条件查询的检索条件不同会需要不同的key,也就需要准备不同的View,这就是View为什么会有多个的原因,因为每一个View只能针对单一类型检索条件。当bucket中出现一个新的View时,就会遍历bucket中的数据,并把最终结果集保存在硬盘上,这个结果集就是Index,也是条件查询时直接查询的数据列表。当数据有所变动时,view不会立刻随之更新,而是受一个定时运行的后台进程管理使之更新,这个周期默认是5000ms(可以自行设置)。除了依靠自动更新外,也可以依赖客户端请求触发更新。客户端进行查询时有三种模式,第一种是直接获取当前存储的Index,第二种是先更新Index然后获取最新的,第三种是获取当前存储的Index并在获得结果后更新Index。显然根据查询压力和Index对同步要求的不同,这个模式要酌情选择。当View有所改变之时,所述Document下所有的View都会重新遍历所有数据来生成新的index,这会造成相当大的I/O压力,这也是为什么要有多个design document。
关于建立View的概念说的差不多了,剩下的细节就看manul补充即可,下面说一下有了View又应该如何查询。没有了传统的SQL语句,我们的查询方式自然也大不一样。这里的查询取决于View。在View中利用函数我们返回了一组key-value值,而我们查询的就是生成的key值,最后返回的则是id-key-value的组合。查询的语法与细节看这个http://docs.couchbase.com/couchbase-manual-2.2/#querying-views,有前端经验的学习起来一定很顺手,因为语法是按照REST来的,只要看一下有哪些参数怎么用就可以了。
最后特别提一点,那就是如何修改数据。在当前版本下,修改数据的方式暂时只有一种:先查询到数据,把这个数据取出,在客户端修改需要修改的部分,再用强制写入的模式把数据存回去,这就是一个完整的修改周期,异常麻烦。
最后就是取出的数据如何方便地抽离。因为取回的是json格式文档,也就是一个长字符串,需要取出相应条目的内容就需要专门的处理。我是用C SDK的,所以我可以借助一个第三方的库,也就是libyajl,这个库可以用来分割就json中的各条目以方便我们使用。yajl可以直接在ubuntu下用apt-get安装,也可以手动安装https://github.com/lloyd/yajl。如果用其他SDK要如何处理我就不清楚了,其他语言的SDK我没研究过,python这类脚本语言本身就有各种库大概直接就能处理了。不过我建议尽量用脚本语言,这样改起来也方便,SDK提供的接口也要更细致更方便,我是只会C才只能用C SDK的,真是麻烦。
总之这里只是讲一下基本概念,具体操作的实施方法需要查阅官方手册,无论是建立View还是查询Index都是有严格语法的,照着manul的教程走就没错了。如果熟悉REST方法的话,查询甚至可以直接用curl或wget加上合适的指令完成,其他工作也可以这样完成,参考http://docs.couchbase.com/couchbase-manual-2.2/#using-the-rest-api和http://docs.couchbase.com/couchbase-manual-2.2/#design-document-rest-api。