首页 > 代码库 > Couchbase第一印象(架构特性)
Couchbase第一印象(架构特性)
Couchbase第一印象(架构特性)
面向文档 保存的字节流总有一个 DOCUMENT ID(Object_ID)
高并发性,高灵活性,高拓展性,容错性好
面向文档的集群存储系统
每个文档用一个唯一的Doc ID
均衡负载
Buckets vs vBuckets
1. Buckets
couchbase的存储逻辑单元叫Bucket
每个bucket有个名字
couchbase 一个节点当前限制10及以下buckets
bucket 有两种类型 couchbase和memcached
bucket有可选的密码控权 SASL authentication
每个bucket有可控的内存配额和复制策略设定,独立可监控和管理
2. vBuckets
主要用来管理维护集群节点之间的bucket分布和路由
doc id的算法使分布式成为可能
Time To Live (TTL)
可用于控制过期时间(默认为一小时)
可用于seesion缓存等功能
后台管理过期,自动删除过期数据,释放内存和硬盘
数据一致性
并发性
Views, Indexs, Queries
Views
这里的views概念完全和SQL的view概念不同
views作为数据翻译转换层,将数据转换为特定格式结构的数据形式如JSON
views 通过 map/reduce功能完成, map将文档结构转换为表输出结构, reduce用来做计数,统计等聚集功能
indexes
每当views建立时, 就会建立indexes, index的更新和以往的数据库索引更新区别很大。 比如现在有1W数据,更新了200条,索引只需要更新200条,而不需要更新所有数据,map/reduce功能基于index的懒更新行为,大大得益。
建立views和index后可以用来Queries
用户用例
替代memcached的缓存层, 提供兼容memcached协议接口
Amazon S3类似服务
session
安装、管理 与客户端接口
三思而后行(安装初始化)
数据存储的路径
Couchbase数据需要持久化到硬盘,需要分配硬盘空间和路径,在Linux与Windows默认是couchbase安装路径
Server Quota(服务缓存层的内存分配)
Couchbase的数据会被缓存,服务层的缓存内存配额配置被各个节点所共享。 如是:现在有一个节点(Node)分配的是2G RAM,那么在加三个节点后,就增加6G RAM来还缓存数据了 ,故一共有8G RAM被分配用来缓存了。
Bucket Quota
集群可以用多个bucket,bucket用来保存一组特别数据或应用,如一个bucket用来做session,另一个bucket用来做做副本。bucket RAM quota的策略,对server quota设定是相辅相成的莲藕关系,很大程度影响cache的内存配额。
安装与管理
Memory Size
Replicas
默认bucket副本是3个。 index replica 开启选项 默认的选项,couchbase的策略比较灵活。只有当数据和节点足够多时,才会开始备份。
Flush
禁用或开启(默认禁用),用于清空bucket的数据
Auto-compaction
持久化的数据和view,index,长期会产生碎片,开启功能时,会自动整理硬盘数据碎片
客户端接口
Python
> pip install couchbase
PHP
$servers = array("192.168.0.72:8091","127.0.0.1:8091");foreach($servers as $server) { $cb = new Couchbase($server, "", "", "default"); if ($cb) { echo "Connected to $server"; break; }}
C
JAVA
基于面向文档的设计开发
Model
JSON
Number (either integer or floating-point).
Boolean
{‘value‘ : true}
String
"hello world"
Array
[1, 4, 5]
Object
{ ‘title‘ : ‘google‘, ‘url‘ : ‘https://www.google.com/‘}
实体之间的关联
内嵌
{ ‘author‘ : ‘Matin‘, ‘books‘ : [ {‘title‘ : ‘Refactor‘ , ‘IBSN‘ : ‘485-566‘},...]}
外部文档,引用其docment id
{ ‘author‘ : ‘Matin‘, ‘books‘ : [ ‘AD3D63D6-2FE0-11E2-93F9-898688C79046_book‘,...]}
事务
存储操作伊始
CURD
- add(id, document [, expiry]) Add an item if ID doesn’t already exist
- set(id, document [, expiry]) Store a document with ID
- replace(id, document [, expiry]) Update the document for an existing ID
- cas(id, document, check [, expiry]) Update the document for an existing ID providing the check matches
- get(id) :Get the specified document
- incr(id [, offset])Increment the document value by offset
- decr(id [, offset] Decrement the document value by offset
- append(id, value) Append the content to the end of the current document
- prepend(id, value) Prepend the content to the beginning of the current document
- delete(id) Delete the specified document
Document Indentifer
与Mongodb相比,Couchbase的存储方式为Key/Value,Value的类型很为单一, 不支持数组。另外也不会自动创建doc id, couchbase需要为每一docment指定一个用于存储的Document Indentifer。
为document创建标示符:
使用唯一的字段做标示符
如在session中,可以使用用户的email, username作为唯一标示符
对象与自增策略
单独创建一自增数据(Document Indentifer),如 add(‘user‘,0) 每次创建一个用户时,可以自增‘user‘, 然后得到 ‘user:1233‘等
使用uuid
标示符的命名规范与最佳实践
使用couchbase的bucket策略 自定义方式 (加前缀)
实践列举:
1. 网站访问量(PAGE VIW) 若我们需要用couchbase统计网站PV 那么命名如 ‘pv:index‘, ‘pv:blog‘, ‘pv:about‘。2. 用户朋友圈 为用户建立一个朋友圈 apend(‘user#1233‘,‘user#444,user#666,‘)
Time To Live (TTL)
常用来做cache,session,购物车使用,验证码等。ttl通过传入一个数字表示, couchbase会对数字作如下的判断:
小于30天(606024*30)的一秒为单位的数字,如600表示10分钟过期。
大于三十天的数字(秒),采用从公元开始的计数,如1381921696表示16th October 2013。
为0的表示永不过期。
保存数据
set和add都是原子性操作,是多线程环境安全的操作。
set(docid, docdata [, expiry])
set不存在docid数据时会创建,存在时替换存在的docid的内容。 过期设定expiry是可选的。
$cb->set(‘message‘, ‘Hello World!‘); $cb->set(‘message‘, ‘Hello World!‘, 10); /*设定过期时限*/ if ($cb->set("spoon", "Hello World!", 10)) { /*操作结果决断*/ echo "Message stored!"; }
add(docid, docdata [, expiry])
与set不同的是,如果docid内容存在时会,会更新失败。
$cb->add(‘message‘, ‘Hello World!‘); /*下面语句会失败*/ $cb->add(‘message‘, ‘I pushed the button, but nothing happened!‘);
获取数据 get(docid)
单文档返回
在php中如果docid不存在会返回undef:
$message = $cb->get(‘message‘)
多文档返回 (Retrieving in Bulk)
不同库的多文档返回实现不同,多文档返回比单独返回要快,因为请求和响应有延迟。 php的会返回一个关联数组:
$ret = $cb->getMulti(array(‘recipe1‘,‘recipe2‘));
更新数据 replace(id, document [, expiry])
在set,add后可以使用replace更新数据:
$message = $cb->get(‘message‘); $message = $message . " How are you today?"; $cb->replace(‘message‘,$message);
并发更新 cas(id, document, check [, expiry])
在并发环境中,有必要保证并发更新
情景一:
1.A 获取了文档‘樱花盛开‘2.B 也获取了文档‘樱花盛开‘3.A 向文档加入信息并更新。4.之后,B 也向文档修改并更新‘樱花盛开‘
这样A的努力完全被B给覆盖了
为了防止以上情况,需要使用cas功能做版本检查
情景 cas版:
1.音 获取了文档‘樱花盛开‘并加入自己的cas id2.暧 也获取了文档‘樱花盛开‘, 并加入自己的cas id3.音 向文档做修改,并使用自己的cas id检查后成功更新。4.之后,暧 也向文档修改并更新‘樱花盛开‘。使用自己的cas id检查后更新失败,因为 音已经更新了,使cas id不一样。
cas如是:检查要更新的文档是不是“原来的版本”(使用get换取的原本)。
$value = http://www.mamicode.com/client->get("customer", NULL, $casvalue); $response = client->cas($casvalue, "customer", "new string value");
cas的缺点是数据更新比起set要慢很多,做大量更新事务并发版本控制并非很完美。另外如果有用户使用set或replace操作不带cas,会使cas失效。
强制锁
cas虽有锁的一些性质,但不能防止期间有不带cas设置的set,replace打乱cas版本。故需要强锁 使用强制锁时,其他用户可以获取数据,但如果没有相应的cas是不能更新文档。
$article = $ai->getAndLock(‘樱花盛开‘, &$cas); $article = ‘樱花飘落的速度是每秒五厘米哦‘; # This will fail, because we are not supplying the CAS value $ai->set(‘樱花盛开‘, $article); # This will succeed and then unlock document $ai->set(‘樱花盛开‘, $article, 0, $cas);
锁也可以设定过期时间,另外也可以释放锁:
$ai->unlock(‘recipe1‘,$cas);
艺术与文学同在(异步)
不同的客户端接口实现不同:
/*使用异步*/ $format_recipe = function($key, $value) { return (‘<li>‘ . $value[‘title‘] . ‘</li>‘); }; $ret = $cb->getDelayed(array(‘recipe1‘,‘recipe2‘),0,$format_recipe); /*单独迭代获取*/ $ret = $cb->getDelayed(array(‘recipe1‘,‘recipe2‘),0,$format_recipe); while ($ret = $cb->fetch()) { echo(‘<li>‘ . $ret[value][‘title‘] . ‘</li>‘); }
服务端更新 (Server-side Updates)
Increment And Decrement
用于页面访问量更新,数据统计等功能:
/*To increment by 1*/ $cb->set(‘counter‘,10); $cb->increment(‘counter‘); /*To increment by 10:*/ $cb->set(‘counter‘,10); $cb->increment(‘counter‘, 10);
Append And Perpend
向文档首尾追加内容:
$user->set(‘userlist‘,‘martin,‘); $user->append(‘userlist‘, ‘stuart,‘); $user->append(‘userlist‘, ‘sharon,‘);
删除数据
当数据存在时,可以使用delete删除:
$cb->delete(‘message‘);
Couchbase第一印象(架构特性)