Couchbase权威指南(十八)

在couchbase里存储数据

couchbase是一个严格的文档型数据库。这就意味着,信息根据文档ID存储在数据库里。没有必要设置数据格式、创建表结构,甚至不需要告诉couchbase关于要存储的信息。你要做的所有工作就是根据指定文档ID存储文档数据。

因为文档的结构原因,在开发应用时有一些不同的考虑点。让我们了解下文档ID和文档值的基本因素。

文档ID

文档ID(或key)非常重要,它用来索引存储的数据。key在一个bucket里必须是唯一的。

key用来标识所存储的信息,可以是任意字串,通常最大长度128位。couchbase没有机制为你自动创建文档ID。假如使用UUID,就必须在你自己的程序里使用对应的UUID库。

通常实践是,使用前缀、类型、分隔符来区分存储在每个bucket里的不同信息。例如,可以使用beer_9834759这个ID来存储关于啤酒的信息。这里的beer前缀标识记录类型,下划线作为分隔符,后面的数字作为唯一的啤酒ID。

couchbase 1.8没有获取文档ID列表的功能,也不能遍历一个bucket里的所有文档。除非指定文档ID,你不能查询信息。然而,这一点会在couchbase 2.0里予以改进和支持。

针对上述问题的一个解决方案是在应用里创建信息链。例如,当一个新的啤酒记录追加到数据库里时,你可以更新一个beer_list的文档,它包含了所有的啤酒记录ID。因为更新是原子性的,所以可以维护这么一份最新的信息列表。实践做法可以参考这篇博客:https://blog.couchbase.com/maintaining-set-memcached

应用程序可以通过使用和读取一个固定的记录来引导自身的数据查询,这个记录要么是本地的配置,要么是在数据库里的配置记录。

发表在 Common | 标签为 | Couchbase权威指南(十八)已关闭评论

Couchbase权威指南(十七)

CAS机制

除了核心函数外,还有一个特殊函数叫做CAS (compare and swap). CAS提供了一个校验合,让多个客户端在同时更新文档时避免产生冲突。

例如,考虑如下场景:

  1. 客户端A获取到文档Martin的值
  2. 客户端B也获取到文档Martin的值
  3. 客户端A修改文档,并更新到数据库
  4. 客户端B也修改文档,并更新到数据库

在上述场景里,客户端B的修改会覆盖掉A修改的值。

为了解决这种情况,可以使用cas()函数。它要求提供从数据库里返回的唯一的CAS值。CAS值在文档更新时,每次都会改变,即使文档更新后的内容不变。将更新发送到服务器时,假如客户端提供的CAS值与服务器里当前存储的CAS不匹配,更新就会失败。

使用CAS后的应用场景如下:

  1. 客户端A获取到文档Martin的值,以及对应的CAS值
  2. 客户端B也获取到文档Martin的值,以及对应的CAS值
  3. 客户端A修改了文档,并且提交到数据库,同时提交CAS,本次更新成功,数据库也同步更新CAS
  4. 客户端B也修改了文档,并且尝试使用CAS进行数据库更新,本次更新失败,因为客户端的CAS与服务器存储的CAS现在不同了

因此,CAS提供了一种检查机制,保证你当前更新的文档自上次获取以来,没有发生变更过。

在编程代码里,CAS是一个类似于update()的函数。取决于环境的不同,你可能先要使用gets()函数来获取到文档信息和CAS值。

例如,在java里先用gets()获取文档信息和CAS值,接着用cas()方法来更新文档:

CASValue customer = client.gets("customer");

CASResponse casr = client.cas("customer", customer.getCas(), "new string value");

CAS的局限性是在客户端库这一级并没有强制执行它。假如你想对所有的更新操作使用CAS,就必须明确的使用它来代替标准的文档更新函数。

发表在 Common | 标签为 | Couchbase权威指南(十七)已关闭评论

Couchbase讨论组

在google groups里建立了一个Couchbase中文讨论组:

Couchbase是开源分布式、面向文档的NoSQL数据库。它是基于集群设计的,通过它的web管理系统,很容易配置一套高性能的集群。扩容方便,性能随着容量增加而线性增加。包括AOL、Linkedin、Zynga等公司在使用它。风河博客(wind.postno.de)翻译了一系列关于Couchbase的文档。

对Couchbase有兴趣童鞋可使用Gmail加入讨论。论坛地址:

https://groups.google.com/d/forum/couchbase-china

发表在 Common | 标签为 | Couchbase讨论组已关闭评论

Couchbase权威指南(十六)

couchbase支持的core协议和操作方法如下表所示。

operations

不管客户端库如何,这些函数在各种语言里工作方式都差不多,可能在语言自己的实现规范上有所不同。例如,可以在ruby里增加一个值:

couchbase.incr("counter", 5)

在.NET里,函数调用是:

client.Increment("counter", 100, 1);

上述第二个参数是假如指定文档ID不存在时的默认值。

发表在 Common | 标签为 | Couchbase权威指南(十六)已关闭评论

Couchbase权威指南(十五)

基本操作

couchbase基于文档ID,执行非常简单的文档存取模型。在存储信息时,不需要定义表或结构,不需要写复杂的查询去获取信息。

couchbase里的所有操作遵循下列规则:

  • 所有操作是原子性的

这意味着服务器里没有锁机制,不可能存在来自多个客户端的并发命令破坏了数据。然而,这也意味着如果多个客户端对同一文档ID执行set操作,只有最后一个操作有效。为了管理这种并发和竞争条件,可以使用CAS操作。这要求提供一个附加的校验值,在校验值不合的情况下,文档不会被更新。

  • 所有数据操作都要求key

所有对数据的操作,都要求提供一个key。不能执行全局操作,或者针对多个key的操作(multiple-get除外)。

  • 没有内部锁

在存储或更新数据时,系统并没有一个内部锁。操作要么完全成功,要么因为某种理由失败(例如,临时内存不足)。

不同的客户端语言执行core协议,从而与couchbase服务器通信:

  • 所有客户端执行core协议

对不同的语言和环境,尽管在结构和函数名字上有些不同,但它们都执行同样的核心操作协议。例如,所有实现里都有set()协议调用,尽管有些客户端把它叫做”store”.

  • 函数调用结构差异

因为不同的语言和环境的差异,对于core协议的函数调用结构也许不同。例如在java里,可变参数方法不可用,因而有多个同一函数的变体。在其他语言里,例如perl、python、ruby,hash是核心变量类型,经常被用来存储和返回信息。

  • 不同的语言提供额外的功能

某些客户端实现提供额外的函数调用和结构,这些是原生core协议所没有的。例如在java里,所有操作既可以是同步也可以是异步的,允许你在get或set操作时,继续处理其他信息。

  • 并非所有实现支持标签

标签在服务器里和数据一起存储,并非被所有语言的客户端支持。

发表在 Common | 标签为 | Couchbase权威指南(十五)已关闭评论

Couchbase权威指南(十四)

配置选项

为了得到最佳的couchbase服务器和客户端环境,你应该使用couchbase客户端的一种。这些smart clients结合了核心接口协议(用来存取数据)和管理协议。后者允许客户端直接与couchbase集群通信,理解vBucket映射表,以便信息能直接发送到集群里的单个节点。在故障转移或rebalance时,同样的机制允许vBucket映射表的变更快速生效。

couchbase直接支持六种客户端库:

  • Java
  • .NET
  • PHP
  • Ruby
  • C (libcouchbase)
  • Python

上述每种都叫做smart client,提供了系统关键功能和集群管理配置的最佳组合。可以从这里了解更多信息:http://www.couchbase.com/communities/all-client-libraries

假如你想使用memcached兼容的库,或者你的应用已经使用了这种协议,那么建议用Moxi服务,它在兼容memcached的同时,又利用了couchbase集群架构的优势。

Moxi代理服务在memcached协议和couchbase集群之间扮演接口角色。couchbase在协议级100%与memcached兼容。你应当在每个客户端安装Moxi,配置Moxi连接到couchbase集群,然后本地程序使用localhost作为主机名连接到Moxi服务。更多信息请参考couchbase官方文档:http://www.couchbase.com/documentation

尽管couchbase兼容memcached协议,但是某些高级couchbase协议是memcached不支持的,这些优势就会利用不上。

发表在 Common | 标签为 | Couchbase权威指南(十四)已关闭评论

Swift容量管理

假如你要往swift集群里增加3T硬盘(标识d16),存储节点IP是192.168.12.104.为了让swift使用它,需要把它加到rings里,例如:

$ swift-ring-builder account.builder add z1-192.168.12.104:6002/d16 3000
$ swift-ring-builder container.builder add z1-192.168.12.104:6001/d16 3000
$ swift-ring-builder object.builder add z1-192.168.12.104:6000/d16 3000

我们使用3000作为权重,它表示3000GB(该磁盘的容量),这种权重设置方法值得借鉴。

然后,对rings进行rebalance,并且拷贝到所有存储节点:

$ swift-ring-builder account.builder rebalance
$ swift-ring-builder container.builder rebalance
$ swift-ring-builder object.builder rebalance

$ scp account.ring.gz swift-node-1:/etc/swift/account.ring.gz
$ scp container.ring.gz swift-node-1:/etc/swift/container.ring.gz
$ scp object.ring.gz swift-node-1:/etc/swift/account.ring.gz
$ scp account.ring.gz swift-node-2:/etc/swift/account.ring.gz
$ scp container.ring.gz swift-node-2:/etc/swift/container.ring.gz
$ scp object.ring.gz swift-node-2:/etc/swift/account.ring.gz
 ...
$ scp account.ring.gz swift-node-10:/etc/swift/account.ring.gz
$ scp container.ring.gz swift-node-10:/etc/swift/container.ring.gz
$ scp object.ring.gz swift-node-10:/etc/swift/account.ring.gz

swift会适应rings改变的结果,每个人都很开心,是这样吗?

继续阅读

发表在 Common | 标签为 | Swift容量管理已关闭评论

Couchbase权威指南(十三)

Hello Couchbase

Couchbase存储信息时,信息的值为文档,键是文档ID。这使得开发和部署应用非常简单。在存储信息时,提供文档内容和对应的文档ID。在获取信息时,提供文档ID就可以获取到对应的值。

只要你知道文档ID,就总可以获取到信息的内容。数据简单的按字节顺序存放。这意味着你既可以存放裸信息(例如字串或整数)、复杂的数据结构(例如JSON),也可以存放序列化对象。序列化会转换特定语言的原生对象为合适的字节串,今后从服务器里获取时,它们又可以还原为对象。

基本的存取过程非常简单。下述示例里我使用了Ruby,不过其他语言的客户端都以相同方式工作,因为它们都使用了相同的核心协议。

安装了ruby客户端库后,就可以编写一段简单的程序来存放信息到couchbase,然后再获取信息。如下是示例的hello-wrold.rb程序:

require 'rubygems'

require 'couchbase'

client = Couchbase.new "http://127.0.0.1:8091/pools/default"

client.quiet = false

begin

spoon = client.get "spoon"

puts spoon

rescue Couchbase::Error::NotFound => e

puts "There is no spoon."

client.set "spoon", "Hello World!", :ttl => 10

end
  • 头两行加载必要的库
  • 下一行打开到couchbase集群的连接。此处定义里,URL必须指向集群里的至少一个节点,这里是本机地址。default表示bucket名字,你可以使用其他bucket,假如已经配置了。
  • 后面的行执行获取和存储操作。假如初次获取操作(针对spoon这个ID)失败,我们就将数据写入到DB里。只要文档ID存在,脚本就打印出对应的存放值。

你可以从命令行运行和测试该脚本。第一次运行时,应该输出这个错误串:

shell> ruby hello-world.rb
There is no spoon.

指定的文档并没有存在于数据库,但随后就加进去了。第二次运行时,就可以打印文档的值:

shell> ruby hello-world.rb
Hello World!

此外,字串文档在存储时,赋予了一个过期时间10秒。这意味着在存放信息后,等待超过10秒信息就被删除了。假如首次运行脚本后,超过10秒再第二次运行该脚本,会输出如下错误串:

shell> ruby hello-world.rb
There is no spoon.

尽管这是一个非常简单的示例程序,它描述了使用基本的get/set操作,在couchbase里存取信息的原理。

发表在 Common | 标签为 | Couchbase权威指南(十三)已关闭评论

Swift安装指南

由于工作需要部署了Swift分布式文件系统,整理了一份安装文档,欢迎阅读。

Swift安装指南

发表在 Common | 标签为 | Swift安装指南已关闭评论

Couchbase权威指南(十二)

Proxy (Moxi)

Couchbase的Moxi组件提供了一个代理服务,允许传统的memcached客户端在不修改应用的前提下,使用couchbase服务。该代理服务提供了在客户端和服务器之间的连接池,在couchbase集群的内部拓扑变更时,它及时通知客户端,从而保证了信息在集群里分布正确。

假如你使用了smart clients客户端库,就不必使用Moxi。

Moxi可以部署在服务端,也可以在客户端。产品环境里在服务端部署Moxi可能会带来问题,建议只部署在客户端。

管理工具

Couchbase被设计为尽可能易用,不要求管理员太多的关注,除了监控健康状态和容量。系统提供了三种途径来管理和监控couchbase服务器和集群。

  • Web管理控制台

Couchbase包含一个内置的web管理控制台,提供了完整的接口功能,包括配置、管理、监控你的服务器。

  • 命令行接口

Couchbase提供了一套命令行工具,用于控制和访问couchbase服务器和集群。可以结合命令行和你自己的脚本和管理过程,来提供附加的功能,比如自动故障转移、备份等。

  • 管理REST API

Web控制台和命令行工具都利用了内置的REST API,API提供了完整的管理功能。所有的管理功能都通过REST API提供,并且它扮演了服务器的认证接口的角色。

因为REST API提供了完善的功能,你可以在自己的管理脚本或程序里使用它,来实现不同的操作。

统计和监控

为了了解couchbase集群正在做什么以及如何执行,系统提供了完整的统计和监控信息。统计信息在所有的管理接口都可以看到。统计系统非常完整,你可以监控和定位到每一个细节。监控系统健康的核心统计报表通过web控制台提供,该报表使用内置的实时图形,允许你实时监控系统的健康和性能状况。

发表在 Common | 标签为 | Couchbase权威指南(十二)已关闭评论