CouchBase2.5.0安装配置

  1. Couchbase简介

Memcache基本上已经是开发的标配了,但是对于Memcache集群,很多线上部署仍然是很单薄的。几个常用的方式:

1,PHP内建支持Memcache::addServer,存取时将key进行Hash,在对应的服务器上进行操作。存在问题:1,不健壮;2,数据不安全;3,配置变更可能导致存取异常

2,引入代理:memcache-agent 或者 moxi ,可以设置数据后备,当一台服务器停止服务时不影响业务。存在问题:后备数据的一致性;

鉴于存在以上问题,Memcache的开发团队开发了Membase,支持多台服务器集群,数据的切片和复制,有效的提高了服务稳定性和数据的安全性,并且支持数据的持久存储。代码的稳定性不够好,我曾经在部分线上业务上使用了Membase,后来因为几次莫名的存取操作缓慢,只能又撤销回到Memcache。

之后,Membase团队与CouchDB团队合并,推出二合一的产品:Couchbase。Couchbase的最大特点:1,完全继承Memcache,原生支持所有Memcache操作;2,继承了Membase的特性,支持集群和数据持久化;3,继承了CouchDB的文档性质,支持通过View对数据进行操作。这个View的特性,提供了以往memcache所不具备的便利性,但是同Mongodb相比又很简单原始,感觉不是一种普遍需求的功能。

  1. 安装Couchbase 2.5.0 64位

系统:RHEL 5.4 X64

1、执行命令:rpm -ivh couchbase-server-enterprise_2.5.0_x86_64_openssl098.rpm

若遇到依赖性错误,通过yum install安装相关依赖的rpm包即可。

2、rpm安装完成后,会自行启动8091端口的应用,此时访问http://xxx.xxx.xxx.xxx:8091进行详细的安装。

上图可自定义安装路径,主机名,加入或者新建一个群集

是否写入样例数据

  1. 配置Couchbase

1、couchbase启动和停止命令。

启动(以下命令都可以):

service couchbase-server start

/opt/couchbase/etc/couchbase_init.d start

/etc/rc.d/init.d/couchbase-server start

停止命令将start换成stop即可。

使用命令 netstat –ntlp|grep :8091可以观察端口是否正常开启

2、组成结构

Bucket的意义,在于将数据进行分隔,比如:任何view就是基于一个bucket的,仅对bucket内的数据进行处理。一个server上可以有多个Bucket,每个Bucket的存储类型、内容占用、数据复制数量等,都需要分别指定。从这个意义上看,每个Bucket都相当于一个独立的实例。在集群状态下,我们需要对server进行集群设置,Bucket只侧重数据的保管。

创建Bucket,需要指明驱动类型: Memcached顾名思义,纯内存,无复制集等功能;Couchbase型是带有持久存储,可以有复制集。

关于复制集,可以设置:禁止复制集、复制集数量(如果设为2,数据将在两个节点上保存,任何一个节点损坏数据仍然存在),是否对索引也进行复制。Flush,是指是否支持清空全部数据的操作。

建议是使用Couchbase类型,设定好内存使用量,其他按默认。关于内存设定,尽量不要将Server上的内存全部分配出去,留一些空闲,对新建Bucket进行测试就很方便。当然,Bucket占用的内存数,在建立后也是可以动态调整的。

后面按照提示进行,设置完管理员密码,服务就可以使用了。在首页的管理界面,可以看到运行的概况。

Couchbase属于nosql系列,个人感觉它要比mongodb操作简单,mongo的查询语句太复杂。在数据的持久性方面它区别于其他nosql 的唯一大亮点是不受限于其内存分配了多少,只要磁盘空间够大,数据就会一直往里面写,也就是说无论给Couchbase分配了多少内存,甚至内存满了,只要磁盘还有空间,内存中的数据也还会慢慢同步到磁盘,Redis在方面就不行,redis内存满了,就不会向磁盘同步数据.couchbase还有一个亮 点就是可以并行同步向多台服务器写数据,甚至在两台不同的服务器同时写同一个key,也无关。

Couchbase 和 Memcache 不同之处在于: Couchbase 是持久话的KEY Value 的存储, Couchbase 还可以做多台机器的数据共享这个类似于MYSQL的数据同步一样,只要添加 Server Nodes 就可以了, Couchbase 还可以建立VIEW进行对数据的查询这点类似于数据库的SQL语句一样。

Couchbase 和 Memcache的区别可在以下网址获得:

http://vschart.com/compare/couchbase/vs/memcached

3、配置群集

在另一台机器也安装了couchbase之后,启动并设置好管理员密码。

然后在第一台机器进行操作,在servernode一栏,点击add server

填入另一台机器的相关信息,下图只是作为示例,IP请填写其他的机器

点击add server

(注意:在增加节点之后,原先服务器上的buckets所有数据会被清空)

点击Rebalance,完成群集的添加,如下图,当前已有两台服务器,新添加的服务器的状态为Pend,等上几秒钟,就会变成绿色的UP了。

4、配置Buckets

Bucket有两种类型,Couchbase和Memcached,区别前面有说明。

点击Create New Data Bucket

Buckets Settings 设置bucket的名称

Memory Size 设置bucket的内存容量大小,只是针对一台node节点的bucket的设定

Access Control 是否需要自定义密码或者端口号

Replicas 是否开启复制,此功能至少一个群里面需要有两个node

Disk Read-Write Concurrency 进行磁盘持久化读写的线程数

Auto-Compaction 是否对持久化的数据或者索引(会产生碎片)进行自动压缩

Flush 是否允许清空bucket的数据

  1. Couchbase存取测试
  2. PHP客户端,请事先安装好apache和php

1、安装git

wget https://git-core.googlecode.com/files/git-1.8.5.5.tar.gz

tar xzvf git-1.8.5.5.tar.gz

cd git-1.8.5.5

./configure –prefix=/usr/local/git

ln -s /usr/local/git/bin/git /usr/local/bin/

2、安装libcouchbase

git clone git://github.com/couchbase/libcouchbase.git

tar xzvf libcouchbase-2.2.0.tar.gz

cd libcouchbase

./configure -prefix=/usr/local/libcouchbase –disable-plugins

make

make install

3、安装php-ext-couchbase

git clone git://github.com/couchbase/php-ext-couchbase.git

tar xzvf php-ext-couchbase-1.2.1.tar.gz

cd php-ext-couchbase

#将以下目录复制到php-ext-couchbase的安装目录中

cp -r /usr/local/libcouchbase/include/libcouchbase/ /setup/php-ext-couchbase

#在php-ext-couchbase当前目录执行/usr/local/php/bin/phpize

./configure -with-php-config=/usr/local/php/bin/php-config

ln -s /usr/local/libcouchbase/lib/libcouchbase.so /usr/lib/libcouchbase.so

ln -s /usr/local/libcouchbase/lib/libcouchbase.so.2 /usr/lib/libcouchbase.so.2

ldconfig

make

make install

重启apache,可以通过/usr/local/php/bin/php –m或者phpinfo()函数查看couchbase模块是否已加载。

4、测试页面代码,保存为.php文件,通过apache访问,可以得到101这个值。

<?php

// adjust these parameters to match your installation

$cb = new Couchbase(“127.0.0.1:8091”, “”, “”, “default”);

$cb->set(“a”, 101);

var_dump($cb->get(“a”));

?>

  1. JAVA客户端

请事先安装好JDK,用到了两个方法,分别是写和读。

put_cb.java

////////////////////////////////////////////////////////////////////////////////

import java.io.IOException;

import java.net.URI;

import java.util.LinkedList;

import java.util.List;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.TimeUnit;

import net.spy.memcached.internal.OperationFuture;

import com.couchbase.client.CouchbaseClient;

public class put_cb {

//文档key

public static final String KEY = “iamkey”;

// expiration time of the document (use 0 to persist forever)

//过期时间(单位毫秒0永久)

public static final int EXP_TIME = 0;

//文档值

public static final String VALUE = “iamvalue3”;

public static void main(String args[]) {

List<URI> uris = new LinkedList<URI>();

//服务器地址(可在Couchbase后台Server NODES中查看)

uris.add(URI.create(“http://10.124.20.173:8091/pools”));

CouchbaseClient client = null;

try {

//在Couchbase后台的Data Buckets中查看

client = new CouchbaseClient(uris, “default”, “”);

} catch (IOException e) {

System.err.println(“IOException connecting to Couchbase: ” + e.getMessage());

System.exit(1);

}

OperationFuture<Boolean> setOp = client.set(KEY, EXP_TIME, VALUE);

//检查是否设置成功

try {

if (setOp.get().booleanValue()) {

System.out.println(“Set Succeeded”);

} else {

System.err.println(“Set failed: ” + setOp.getStatus().getMessage());

}

} catch (InterruptedException e) {

System.err.println(“InterruptedException while doing set: ” + e.getMessage());

} catch (ExecutionException e) {

System.err.println(“ExecutionException while doing set: ” + e.getMessage());

}

System.out.println();

//完成操作后3秒后关闭client

client.shutdown(3, TimeUnit.SECONDS);

System.exit(0);

}

}

////////////////////////////////////////////////////////////////////////////////

get_cb.java

////////////////////////////////////////////////////////////////////////////////

import java.io.IOException;

import java.net.URI;

import java.util.LinkedList;

import java.util.List;

import java.util.concurrent.TimeUnit;

import com.couchbase.client.CouchbaseClient;

public class get_cb

{

public static void main(String[] args)

{

List<URI> uris = new LinkedList<URI>();

uris.add(URI.create(“http://10.124.20.173:8091/pools”));

CouchbaseClient client = null;

try {

client = new CouchbaseClient(uris, “default”, “”);

} catch (IOException e) {

System.err.println(“IOException connecting to Couchbase: ” + e.getMessage());

System.exit(1);

}

 

Object o = client.get(“iamkey”);

System.out.println(o);

System.out.println(“the “+i+” time”);

client.shutdown(20, TimeUnit.SECONDS);

System.exit(0);

}

}

////////////////////////////////////////////////////////////////////////////////

运行以上方法需要couchbase client的jar包支持,可以官网下载:

http://packages.couchbase.com/clients/java/1.3.2/Couchbase-Java-Client-1.3.2.zip

1、Windows下java测试方法:

1、将以下内容分别保存为put_cb.bat和get_cb.bat

@echo off&setlocal enabledelayedexpansion

set LIB=%cd%\couchbase_jar

echo %LIB%

set CLASSPATH=.

FOR %%C IN (%LIB%\*.jar) DO set CLASSPATH=!CLASSPATH!;%%C

echo %CLASSPATH%

javac get_cb.java

java get_cb

pause

2、将put_cb.java和get_cb.java与上述两个bat文件放在同一目录下

注意路径中不能包括空格

3、将couchbase client的jar包解压并目录名改为couchbase_jar,也放在同一目录下。

4、双击运行bat即可。

2、RHEL下测试方法:

请事先安装好JDK

用到的方法如下:

HelloWorld.java

////////////////////////////////////////////////////////////////////////////////

import com.couchbase.client.CouchbaseClient;

import java.net.URI;

import java.util.Arrays;

import java.util.List;

 

public class HelloWorld {

 

public static void main(String[] args) throws Exception {

 

// (Subset) of nodes in the cluster to establish a connection

List<URI> hosts = Arrays.asList(

new URI(“http://10.124.20.173:8091/pools”)

);

 

// Name of the Bucket to connect to

String bucket = “default”;

 

// Password of the bucket (empty) string if none

String password = “”;

 

// Connect to the Cluster

CouchbaseClient client = new CouchbaseClient(hosts, bucket, password);

 

// Store a Document

client.set(“my-first-document”, “Hello Couchbase!”).get();

 

// Retreive the Document and print it

System.out.println(client.get(“my-first-document”));

 

// Shutting down properly

client.shutdown();

}

}

////////////////////////////////////////////////////////////////////////////////

将couchbase client的jar包解压与HelloWorld.java放在统一目录下,执行命令如下:

编译

javac -cp couchbase-client-1.3.2.jar:spymemcached-2.10.5.jar \

HelloWorld.java

运行

java -cp .:couchbase-client-1.3.2.jar:spymemcached-2.10.5.jar:\

jettison-1.1.jar:netty-3.5.5.Final.jar:commons-codec-1.5.jar:\

httpcore-4.3.jar:httpcore-nio-4.3.jar HelloWorld

  1. C客户端

需要的组件为libcouchbase-2.2.0.tar.gz,前面进行php客户端安装时已完成安装,现在只需调用即可。

因为当时安装libcouchbase是指定了安装位置/usr/local/libcouchbase,所以在编译c文件时要注意头文件的位置。

1、C代码如下,保存为文件test_cb.c:

#include <libcouchbase/couchbase.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

static void error_callback(lcb_t instance,

lcb_error_t err,

const char *errinfo)

{

fprintf(stderr, “Error %s: %s”, lcb_strerror(instance, err),

errinfo ? errinfo : “”);

exit(EXIT_FAILURE);

}

 

/* the callback invoked by the library when receiving a get response */

static void get_callback(lcb_t instance,

const void *cookie,

lcb_error_t error,

const lcb_get_resp_t *resp)

{

if (error != LCB_SUCCESS) {

fprintf(stderr, “Failed to retrieve \”“);

fwrite(resp->v.v0.key, 1, resp->v.v0.nkey, stderr);

fprintf(stderr, “\”: %s\n“, lcb_strerror(instance, error));

} else {

fprintf(stderr, “Data for key: \”“);

fwrite(resp->v.v0.key, 1, resp->v.v0.nkey, stderr);

fprintf(stderr, “\” is:\n“);

fwrite(resp->v.v0.bytes, 1, resp->v.v0.nbytes, stderr);

fprintf(stderr, “\n“);

}

(void)cookie; /* ignore */

}

 

int main(void)

{

struct lcb_create_st create_options;

lcb_t instance;

lcb_error_t err;

 

memset(&create_options, 0, sizeof(create_options));

create_options.v.v0.host = “localhost:8091”;

create_options.v.v0.user = “beer-sample”;

create_options.v.v0.passwd = NULL;

create_options.v.v0.bucket = “beer-sample”;

 

err = lcb_create(&instance, &create_options);

if (err != LCB_SUCCESS) {

fprintf(stderr, “Failed to create libcouchbase instance: %s\n“,

lcb_strerror(NULL, err));

return 1;

}

 

/* set up the handler to catch all errors */

lcb_set_error_callback(instance, error_callback);

 

/* initiate the connect sequence in libcouchbase */

err = lcb_connect(instance);

if (err != LCB_SUCCESS) {

fprintf(stderr, “Failed to initiate connect: %s\n“,

lcb_strerror(NULL, err));

return 1;

}

 

/* run the event loop and wait until we’ve connected */

lcb_wait(instance);

 

/* set up a callback for our get requests */

lcb_set_get_callback(instance, get_callback);

 

{

lcb_get_cmd_t cmd;

const lcb_get_cmd_t *commands[1];

 

commands[0] = &cmd;

memset(&cmd, 0, sizeof(cmd));

cmd.v.v0.key = “second_street_brewery”;

cmd.v.v0.nkey = strlen(cmd.v.v0.key);

 

err = lcb_get(instance, NULL, 1, commands);

if (err != LCB_SUCCESS) {

fprintf(stderr, “Failed to get: %s\n“,

lcb_strerror(NULL, err));

return 1;

}

}

 

lcb_wait(instance);

 

lcb_destroy(instance);

exit(EXIT_SUCCESS);

}

2、将libcouchbase目录中的头文件目录复制到/usr/include目录

cp –r /usr/local/libcouchbase/include/libcouchbase/ /usr/include/

3、编译test_cb.c并输出为test_cb

gcc -lcouchbase test_couchbase.c -o test_cb

4、运行./test_cb,输出结果如下:

Data for key: “second_street_brewery” is:

{“name”:”Second Street Brewery”,”city”:”Santa Fe”,”state”:”New Mexico”,”code”:”87505″,”country”:”United States”,”phone”:”1-505-982-3030″,”website”:”http://www.secondstreetbrewery.com/”,”type”:”brewery”,”updated”:”2010-07-22 20:00:20″,”description”:””,”address”:[“1814 Second Street”],”geo”:{“accuracy”:”RANGE_INTERPOLATED”,”lat”:35.6631,”lon”:-105.966}}

  1. Couchbase View功能试用

View的原理是对“某个bucket已经存储到硬盘上的所有数据进行map/reduce操作,并可将结果持久保存”。

View是属于某个Bucket,一个View有一个document,下面可以有多个view。view分Development Views和Production Views。前者可以修改,通过Publish按钮转换成生产模式。

通俗来说view的作用就是将存储在bucket中的目标数据通过javascript语法进行转换筛选,然后返回所需要的值,使用到map和reduce这两个方法。这跟数据库的view功能是差不多的。

通过使用Couchbase默认的bucket beer-sample来测试view的使用:

1、若当时没有选择附带beer-sample这个bucket,可以在setting,samle bucket中新增;

2、点击View列表,在下来框中选中beer-sample,点击创建,名称要完全与图中一致,_design/dev_beer 和 beer_by_name

3、点击 edit,进入view的编辑界面。

4、在map中输入以下代码,点击save保存

function (doc, meta) {

if (doc.type == “beer”) {

emit(doc.name);

}

}

5、点击show result,可以看到对数据运行map中的函数所获取的结果,大致意思是如果type等于beer,就输出这条数据中的name字段。

6、这里用PHP演示获取view的返回数据,php代码如下,保存为test.php:

<?php

$cb = new Couchbase(“127.0.0.1:8091”, “beer-sample”, “”, “beer-sample”);

$result = $cb->view(“dev_beer”, “beer_by_name”);

foreach($result[“rows”] as $row) {

echo $row[‘key’] . “<br/>“;

}

在IE中浏览此页面,显示如下:

也可以将上述语句的result语句改成如下:

$result = $cb->view(“dev_beer”, “beer_by_name”);

改为

$result = $cb->view(‘dev_beer’, ‘beer_by_name’, array(‘startkey’ => ‘O’, ‘endkey’ => ‘R’));

访问页面显示结果如下,由O开始,在R之前结束:

在PHP的view函数中,第一个参数是文档,第二个是view,第三个是参数。其中,最重要的两个参数:

1,stale :  false时,每次都新生成数据;ok,使用上次生成的缓存;update_after,使用缓存数据立刻返回,之后刷新数据

2,reduce: 是否执行reduce函数。如果不执行,则返回所有map后的数据

上述的示例就是只执行了map方法,所以所显示的结果为map的返回结果,可以通过编写reduce方法对map返回的数据进行再一次处理。

既往使用memcached的时候,对其中的数据进行批量处理会是非常困难的事情,couchbase的view功能,使其从单一缓存工具转变为文档型数据库。但是,这个功能也有些蛋疼,要map全部数据,性能上很成问题。可以通过设置更多的bucket,尽量让一类数据放在一个bucket上,可以改善一些。但总体来看瑕不掩瑜,View功能让通过缓冲进行数据统计分析成为可能,这是一个很可喜的事情。

  1. Couchbase运维相关

1、如何在同一Server下建立多个Bucket?

与membase时类似,默认的bucket是11211端口,可以建立多个Bucket复用这个端口,但是需要客户端连接是通过SLD验证来确定到底连接哪一个Bucket。另一个更实用的办法,是将更多的Bucket分别建立在不同的端口上。这与以往在一台服务器上运行多个memcache实例是相似的。

2、出现某台服务器宕机的情况,数据存取出现异常,怎么回事?

当某个node失效时,在管理界面中可以看到该节点处于down状态。注意,这时PHP连接时,仍然会试图将对此node进行操作,从而返回false。这与我们理解上的集群应该自动保持有效的想法是有差异的。需要手工点击“Fail Over”将此node从服务中屏蔽,之后php才不会对此node进行操作。当节点重新启动后,需要将其恢复回来。根据提示点击“Add Back”,然后视情况决定是否执行Rebalance。

尤其是在只有两个节点时,意味着一个节点失效,如果不及时进行干预,就会有超过一半的请求失败(默认失效节点为主的写和轮询的读),结果会很惨。这看似很傻,其实是为了保证数据有效性。

根据官方解释:

A,node少于3个时,必须手工干预;

B,node大于等于3个时,可以通过REST接口设置为“Auto Failover”

C,可以进一步设定,当节点数大于某个数值时,进行自动failover

这样的设定使得大集群可以有效的工作,不会因为运维经验不足导致数据永久损失。这种考虑还是很值得认可的。

3、其他注意事项

  • 尽量使用failover
  • 少用rebalance
  • 有出问题且无法恢复,先停止该节点进程再执行删除
  • 设置bucket的数据目录,不要存储在默认位置
  • 对使用内存要求不同的数据使用不同的bucket,设置不同的内存资源
  • 对非重要数据不做replicate备份。
  • couchbase-1.8的离线备份速度非常慢,占CPU非常高,能看到是使用sqlite3命令备份的。
  • 不要存储大于50K的文本数据或二进制数据。
  • couchbase-1.8.0某个bucket太大(>200G,分配内存比较小1-2G),可能导致重启动后无法恢复,一直处理pend状态,无法提供服务。
  • 太大的bucket还是导致无法加入新的节点,也是一直处理pend状态,无法提供服务。
  • 不要在centos-5.4系统及更低版本系统上安装,系统负载稍大(load>80)可能会出些couchbase宕机问题。

部分内容参考自:http://hi.baidu.com/cnjimmydong/item/e08ecf1aa7d44612d0d66d88

Couchbase官方社区:http://www.couchbase.com/communities/

所有Couchbase客户端版本下载页面:

http://www.couchbase.com/communities/all-client-libraries