一.什么是Couchbase Server
大数据的Nosql技术已发展成熟,这以MongoDB为代表,但我这里要介绍的是另一种Nosql技术,叫做Couchbase Server,近年来在国外发展迅猛,大有超过MongoDB之势。Couchbase Server是由早先的CouchDB发展而来,继承了Memcached的技术特性,是一个开源的、分布式的、面向文档(document-oriented)的Nosql数据库,具有许多优越核心功能:
二.Couchbase Server 3.02与MongoDB 3.0的对比
据新动力咨询公司做的一项
针对Couchbase Server 3.02与MongoDB 3.0的性能测试报告,在相同硬件的类似集群配置(因两者拓扑架构不同,不能做到相同)下,Couchbase在下列4个方面超过MongoDB:
1.并发Couchbase展示了较好的并发性,能比MongoDB处理三倍多的并发用户
2.吞吐量Couchbase展示了较高的吞吐量,甚至在相同数量的并发用户下,Couchbase Server比MongoDB能提供2.5倍的吞吐量
3.延迟Couchbase展示了较低的延迟。即使在相同数量的并发用户下,Couchbase能够提供比MongoDB低4-5倍的延迟
4.性价比在相同硬件并满足相同延迟值的要求下,Couchbase Server比mongodb能够提供2.5倍甚至4.5倍的吞吐量。这样,Couchbase Server的操作费用将只有
MongoDB的22-44%。
如今许多互联网巨头都迁移到
Couchbase Server上了,如paypal、linkedin、ebay、GE等。
三.如何安装
下面以windows系统为例:
一 首先,到官网下载安装包:http://www.couchbase.com/nosql-databases/downloads,可根据你的的硬件操作系统选择所要的安装包,这里为方便起见选择了64位的企业windows版couchbase-server-enterprise_4.1.0-windows_amd64.exe,安装系统最小需要内存为 4G,处理
器最小为 4 核处理器; 同时从此网站上再下载一个Java版的应用程序包Couchbase-Java-Client-2.2.5.zip,以便后面开发应用项目之用。
然后点击这个exe文件开始安装,选择安装的路径,确认安装所需的最小内存大小和处理器个数完成安装。
二.配置
完成安装之后,直接就会
进入一个管理界面进行配
置。另外,在桌面上,安装程序默认就会生成一个快捷方式。点击设置按钮,进入5个设置步骤:
1.配置服务器
设置磁盘存储路径,服务器主机,是否生成一个新
集群还是加入已有一个集群中。
2.安装示例数据
安装系统提供两个样品数据桶bucket (下面将详细介绍)和MapReduce,可选择安不安装
3.创建默认的
桶(bucket)
设置桶类型(Couchbase或Memcached)、每个节点使用的内存大小、备份
、磁盘读写同步工作个数以及冲洗Flush。
5.配置
服务器
设置管理员的口令,注意帐号名和密码要区分大小写
6.配置完成之后,进入
监控web页面console。以后可以点击桌面快捷图标打开,在此监控页面上就可以看到
服务器的使用情况并可查看和编辑
数据。整个console共有8个Tab页面:
集群概况
、服务器节点
、数据桶(bucket)、视图、索引、跨数据中心备份、日志和设置。
a"集群概况(Cluster Overview)
当前时间段上桶的操作
图和磁盘读取图以及服务器当前活动状况,见上图
b:服务器节点(Server Nodes)
、活动状态、何种服务、内存
使用
、交换使用、cpu
使用、磁盘使用、数据项数(
活跃/备份)。还可进行添加
服务器、除去
服务器、分组服务器、更换服务器等操作
c:数据桶(Data Buckets)
(bucket)是一种新概念,相当于关系型数据库中的Schema,即
数据存储区间
。每一个bucket都包含活跃和备份的数据集,并映射到1024个逻辑分区(Virtual Bucket,简称vBucket),文档的读取写入等操作只与分区vBuckets打交互。相同的文档ID,每次都被哈希到相同的分区,分区vBucket可以在节点之间移动(rebalance),vBucket和物理服务器之间的对应关系被存储在cluster map中。
在此Tab上,不仅可以监控各个
数据桶的使用状况,还可创建新的数据桶,建立新文档,查看、修改和删除已有文档
d:视图(Views)
视图是一种可视化的表,在Couchbase中以两种格式(设计和生产)文档存储在
数据桶中,每张视图由一名字和一组MapReduce函数表示。
其必须Map
描述了怎样从数据桶中提取数据,而可选Reduce函数描述了怎样聚合其结果。
在此Tab中,可以查看视
图数据并可进行过滤排序等操作,还可创建、删除和编辑设计视图的Java文档,并发布为生产视图
e:Index(索引)
Couchbase提供有三种用于不同服务的索引:
·MapReduce
视图
索引,是线性增加的,只当文档有变化时才重新索引;
·立体视图索引,Couchbase使用立体视图来查询
地理空间
信息,一个立体视图含有地理空间数据,基于所记录的数据是否在一给定的多维范围内来
查询所要信息。他们也用于非几何多维范围内的查询,不像MapReduce视图
有两个
函数map和reduce,立体视图只有一个函数spatial,类似于前者函数map。
数据扫描,不像视图索引,其索引值仅局部每个节点,全局第二索引是建立在整个集群上的
f:XDCR(跨数据中心备份)
XDCR提供了一种把
数据从一个
集群备份到另一个
集群的便利方式,可把活跃数据拷贝到N+1个Couchbase服务器集群或外部应用(如Elastic,Spark,Storm等),这些集群常用于多个地理分散的灾难恢复或为快速传输而接近实际用户,这种备份可设为双向或多向。
在此Tab页面上,可以方便创建多个运种
集群,设置备份参数。
g:日志(Log)
Tab记录了事件
、模块代码、服务器节点和时间的日志,可用于诊断Couchbase集群内的活动和错误。
h:设置(Setting)
设置Tab页面用于设置你的Couchbase服务器全局参数,包括集群配置
、更新通知、自动修复、报警、自动压缩、帐号管理、审计和样品数据桶。
三.开发实例
当安装并设置好Couchbase
服务器
集群(只一台服务器也构成一个集群)后,就可以进行应用开发了。将前面下载的Couchbase-Java-Client-2.2.5.zip解压,将其中的三个jar包: couchbase-core-io-1.2.5.jar、couchbase-java-client-2.2.5.jar、rxjava-1.0.15.jar加入你所用的IDE库中。
首先,你需要做的是连接
集群:
Cluster cluster = CouchbaseCluster.create();
当不带参数时,则此连接逻辑上与localhost相连的
集群绑定,这种做法在开发
环境下是可以的,但在生产环境下需要指定服务器节点,如下所示:
Cluster cluster = CouchbaseCluster.create("192.168.56.101","192.168.56.102");你不必把集群中每个节点都列上,只需几个种子节点以便客户可以建立
起初始连接,实际连接是当调用openBucket方法时才建立起与数据桶的真正连接:
Bucket bucket=cluster.openBucket();这只是连接缺省的数据桶,并返回Bucket引用。如果你想连接一个不同的数据桶,你需通过console界面预先创建好一个数据桶才可连接,代码如下:
Bucket bucket = cluster.openBucket("bucket","password");当应用关闭时,你必须断开与集群的连接以确保释放所有资源(如sockets,threads,等),下面代码关闭客户:cluster.disconnect();这断开所有数据桶并释放全部资源。现在有了Bucket引用,就可以操作JSON文档了。首先,生成一个用户的JsonObject:
JsonObjectuser = JsonObject.empty()
.put("firstname","Walter")
.put("lastname","White")
.put("job","chemistry teacher")
.put("age",50);
JsonObject的作用非常类似Map,但被设计仅用于插入值,以便存为有效的JSON(包括嵌套对象和数组),所生成的结果文档类似如下:
{
"firstname":"Walter",
"job":"chemistry teacher",宋体; line-height:26px"> "age":50,宋体; line-height:26px"> "lastname":"White"
}
为存储文档,需调用bucket的upsert方法。由于服务器上的文档具有多种特性,需要给他赋予一个唯一文档ID,如walter:
JsonDocument doc = JsonDocument.create("walter",user);
JsonDocument response =
bucket.upsert(doc);
这个Document将自动转换为JSON并存入集群中,如果这个文档ID已经存在它将被替换。Bucket提供了诸多如插入(insert)、获取(get) 、删除(remove) 、关闭(close)等方法,为调用方便,我把他们写在一个称为ConnectionManager类里:package com.couchbase.beersample;import java.util.ArrayList;import java.util.NoSuchElementException;import java.util.concurrent.CountDownLatch;import rx.Observable;import rx.Subscriber;import rx.functions.Action1;import rx.functions.Func1;import com.couchbase.client.java.*;import com.couchbase.client.java.document.JsonDocument;import com.couchbase.client.java.view.AsyncViewResult;import com.couchbase.client.java.view.AsyncViewRow;import com.couchbase.client.java.view.Stale;import com.couchbase.client.java.view.ViewQuery;/** * The ConnectionManager handles connecting,disconnecting and managing of the * Couchbase connection. */public class ConnectionManager { //生成一个静态instance private static final ConnectionManager connectionManager = new ConnectionManager(); public static ConnectionManager getInstance() { return connectionManager; }//生成一个静态集群 static Cluster cluster = CouchbaseCluster.create(); //打开一个数据桶,这里为beer-sample,安装时自动生成的 static Bucket bucket = cluster.openBucket("beer-sample"); //关闭集群 public static void disconnect() { cluster.disconnect(); } //得到视图的行集合列表,这里使用异步获取方式 public static ArrayList<AsyncViewRow> getView(String designDoc,String view) { final ArrayList<AsyncViewRow> result = new ArrayList<AsyncViewRow>(); final CountDownLatch latch = new CountDownLatch(1); bucket.async().query( ViewQuery.from(designDoc,view).limit(20).stale(Stale.FALSE)) .doOnNext(new Action1<AsyncViewResult>() { @Override public void call(AsyncViewResult viewResult) { if (!viewResult.success()) { System.out.println(viewResult.error()); } } }).flatMap(new Func1<AsyncViewResult,Observable<AsyncViewRow>>() { @Override public Observable<AsyncViewRow> call(AsyncViewResult viewResult) { return viewResult.rows(); } }).subscribe(new Subscriber<AsyncViewRow>() { @Override public void onCompleted() { latch.countDown(); } @Override public void (Throwable throwable) { System.err.println("Whoops: " + throwable.getMessage()); } @Override public void onNext(AsyncViewRow viewRow) { result.add(viewRow); } }); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } return result; }//获取一个Json文档 public static JsonDocument getItem(String id) { JsonDocument response = null; try { response = bucket.get(id); } catch (NoSuchElementException e) { System.out.println("ERROR: No element with message: " + e.getMessage()); e.printStackTrace(); } return response; } //删除一个Json文档 public static void deleteItem(String id) { try { bucket.remove(id,PersistTo.MASTER); } catch (NoSuchElementException e){ System.out.println("ERROR: No element with message: " + e.getMessage()); } } //更新一个Json文档 public static void updateItem(JsonDocument doc) { bucket.upsert(doc); } //关闭数据桶的连接 public static void closeBucket() { bucket.close(); }}为演示目的,这里举一个把啤酒beer信息存储到Couchbase里的应用例子,先要建立一个BeerModel类:package com.couchbase.beersample;public class BeerModel{ private String name,style,deion,category,abv,srm,ibu,upc,brewery,Id = ""; public String getName(){ return name; } public void setName(String name){ this.name = name; } public String getStyle(){ return style; } public void setStyle(String style){ this.style = style; } public String getDeion() { return deion; } public void setDeion(String deion) { this.deion = deion; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public String getAbv() { return abv; } public void setAbv(String abv) { this.abv = abv; } public String getSrm() { return srm; } public void setSrm(String srm) { this.srm = srm; } public String getIbu() { return ibu; } public void setIbu(String ibu) { this.ibu = ibu; } public String getUpc() { return upc; } public void setUpc(String upc) { this.upc = upc; } public String getBrewery() { return brewery; } public void setBrewery(String brewery) { this.brewery = brewery; } public String getId(){ return Id; } public void setId(String id) { this.Id = id; }}再建造一个Main类,在main函数里进行测试,package com.couchbase.beersample;import com.couchbase.client.java.document.JsonDocument;import com.couchbase.client.java.document.json.JsonObject;import com.couchbase.client.java.view.AsyncViewRow;import java.util.ArrayList;import rx.functions.Action1;import rx.functions.Func1;/** * * @author Xijian */public class Main { public static void main(String[] args) { BeerModel beerModel = new BeerModel(); beerModel.setId("2"); beerModel.setName("beer2"); beerModel.setStyle("beer2 style"); beerModel.setDeion("beer2 Deion"); beerModel.setAbv("beer2 abv"); beerModel.setIbu("beer2 ibu"); beerModel.setSrm("beer2 srm"); beerModel.setUpc("beer2 upc"); beerModel.setBrewery("beer2 Brewery id"); JsonObject beer = JsonObject.empty() .put("name",beerModel.getName()) .put("style",beerModel.getStyle()) .put("deion",beerModel.getDeion()) .put("abv",beerModel.getAbv()) .put("ibu",beerModel.getIbu()) .put("srm",beerModel.getSrm()) .put("upc",beerModel.getUpc()) .put("brewery",beerModel.getBrewery()) .put("type","beer"); JsonDocument doc = JsonDocument.create(beerModel.getId(),beer); ConnectionManager.updateItem(doc); beerModel = new BeerModel(); beerModel.setId("3"); beerModel.setName("beer3"); beerModel.setStyle("beer3 style"); beerModel.setDeion("beer3 Deion"); beerModel.setAbv("beer3 abv"); beerModel.setIbu("beer3 ibu"); beerModel.setSrm("beer3 srm"); beerModel.setUpc("beer3 upc"); beerModel.setBrewery("beer3 Brewery id"); beer = JsonObject.empty() .put("name","beer"); doc = JsonDocument.create(beerModel.getId(),beer); ConnectionManager.updateItem(doc); ArrayList<AsyncViewRow> result = ConnectionManager.getView("beer","by_name"); System.out.println("size: " + result.size()); doc = ConnectionManager.getItem("2"); System.out.println("name: " + doc.content().getString("name")); }}运行Main类,将得到如下结果: size: 2 name: beer2其次,打开管理员console页面,进入Views Tab中,在顶上一行的>Views>之前的下拉单里选取beer-sample,然后点击按钮Create Development View,在弹出的窗口中,Design Document Name: 框下填入name,View Name:框下填入by_name,再点击Save按钮存入,此时View Code的分区展开,有两个窗口,左边为Map窗,内含缺省函数,function (doc,Meta) { emit(Meta.id,null); }右边为Reduce窗,缺省为空。修改Map函数为 function (doc,Meta) { if(doc.type && doc.type == "beer") { emit(doc.name,doc.brewery_id + "," + doc.style); } }Reduce窗不变,点击Save按钮存入。再点击下面的Show Results则显示如下视图结果:
你还可以过滤这些结果(需点击Filter Results箭头icon),确定这些结果正确之后就可以把其发布到生产环境上去,这可通过点Publish按钮完成。
原文链接:https://www.f2er.com/nosql/203547.html