1. 简介

本文介绍 Couchbase Java SDK 的核心用法,涵盖基础概念和操作场景:

  • 创建 Couchbase 环境
  • 连接集群
  • 打开数据桶(Bucket)
  • 执行基础持久化操作
  • 处理文档副本

2. Maven 依赖

使用 Maven 时,在 pom.xml 中添加以下依赖:

<dependency>
    <groupId>com.couchbase.client</groupId>
    <artifactId>java-client</artifactId>
    <version>2.7.2</version>
</dependency>

3. 快速上手

SDK 提供 CouchbaseEnvironment 接口和默认实现类 DefaultCouchbaseEnvironment,用于管理集群和数据桶的访问配置。默认设置可按需覆盖(详见 3.2 节)。

踩坑提醒:官方文档强调,JVM 中必须保持唯一CouchbaseEnvironment 实例,多个实例可能导致不可预测的行为。

3.1. 使用默认环境连接集群

通过集群节点 IP/主机名直接连接,SDK 自动创建默认环境:

// 连接单节点集群(本地开发)
Cluster cluster = CouchbaseCluster.create("localhost");

// 连接多节点集群(生产环境推荐)
Cluster cluster = CouchbaseCluster.create("192.168.4.1", "192.168.4.2");

注意:无需指定所有节点,连接建立后 SDK 会自动发现集群中的其他节点。

3.2. 使用自定义环境

当需要调整默认配置时,可构建自定义环境:

// 创建自定义环境(连接超时10秒,KV操作超时3秒)
CouchbaseEnvironment env = DefaultCouchbaseEnvironment.builder()
  .connectTimeout(10000)
  .kvTimeout(3000)
  .build();

// 单节点连接
Cluster cluster = CouchbaseCluster.create(env, "localhost");

// 多节点连接
Cluster cluster = CouchbaseCluster.create(env, "192.168.4.1", "192.168.4.2");

3.3. 打开数据桶

连接集群后,打开目标数据桶:

// 打开无密码的默认桶
Bucket bucket = cluster.openBucket();

// 显式指定桶名(无密码)
Bucket bucket = cluster.openBucket("default");

// 打开无密码的自定义桶
Bucket myBucket = cluster.openBucket("myBucket");

// 打开带密码的桶
Bucket bucket = cluster.openBucket("bucketName", "bucketPassword");

4. 持久化操作

本节演示 CRUD 操作,以人员文档为例:

{
  "name": "John Doe",
  "type": "Person",
  "email": "john.doe@example.com",
  "homeTown": "Chicago"
}

最佳实践type 字段用于区分同桶中的不同文档类型。

4.1. 文档 ID

  • Couchbase 文档通过唯一 ID 标识(类似关系数据库的主键)
  • ID 必须是 UTF-8 字符串,长度 ≤ 250 字节
  • Couchbase 不自动生成 ID,需自行实现,常用策略:
    • 自然键派生(如用邮箱地址)
    • 随机 UUID(本文示例使用此方案)

4.2. 插入文档

// 构建文档内容
JsonObject content = JsonObject.empty()
  .put("name", "John Doe")
  .put("type", "Person")
  .put("email", "john.doe@example.com")
  .put("homeTown", "Chicago");

// 创建文档对象
String id = UUID.randomUUID().toString();
JsonDocument document = JsonDocument.create(id, content);

// 插入文档(ID冲突时抛出 DocumentAlreadyExistsException)
JsonDocument inserted = bucket.insert(document);

// 插入或更新(无则插入,有则更新)
JsonDocument upserted = bucket.upsert(document);

4.3. 获取文档

// 通过ID获取文档(不存在返回null)
JsonDocument retrieved = bucket.get(id);

4.4. 更新文档

// 修改文档内容
JsonObject content = document.content();
content.put("homeTown", "Kansas City");

// 更新文档(无论是否存在)
JsonDocument upserted = bucket.upsert(document);

// 仅更新已存在文档(不存在抛出 DocumentDoesNotExistException)
JsonDocument replaced = bucket.replace(document);

4.5. 删除文档

// 通过文档对象删除
JsonDocument removed = bucket.remove(document);

// 通过ID删除
JsonDocument removed = bucket.remove(id);

删除结果:返回的 JsonDocument 仅包含 ID 和 CAS 属性,内容已被清除。
异常处理:文档不存在时抛出 DocumentDoesNotExistException

5. 处理文档副本

5.1. 虚拟桶与副本机制

  • Couchbase 将文档分布在 1024 个虚拟桶(vbucket)
  • 通过文档 ID 的哈希值确定存储位置
  • 每个桶可配置 1~3 个副本(replica)
  • 副本与主桶存储在不同节点,实现高可用

5.2. 从副本读取文档

当主节点不可用时,可从副本读取:

// 尝试主节点读取,失败后读取副本
JsonDocument doc;
try {
    doc = bucket.get(id);
} catch (CouchbaseException e) {
    List<JsonDocument> replicas = bucket.getFromReplica(id, ReplicaMode.FIRST);
    if (!replicas.isEmpty()) {
        doc = replicas.get(0);
    }
}

高级场景:获取所有副本并选择最新版本(通过 CAS 值判断):

long maxCasValue = -1;
for (JsonDocument replica : bucket.getFromReplica(id, ReplicaMode.ALL)) {
    if (replica.cas() > maxCasValue) {
        doc = replica;
        maxCasValue = replica.cas();
    }
}

性能权衡:副本读取可能返回旧数据,因写入通常异步复制到副本。

6. 总结

本文涵盖了 Couchbase Java SDK 的核心操作场景:

  • 环境配置与集群连接
  • 桶操作与文档 CRUD
  • 副本读取机制

完整代码示例见 GitHub 项目
深入学习请参考 官方文档


原始标题:Introduction to Couchbase SDK for Java