BookKeeper 介紹(3)--API

且行且码發表於2024-06-23

本文主要介紹 BookKeeper 的 API,文中所使用到的軟體版本:Java 1.8.0_341、BookKeeper 4.16.5。

1、引入依賴

<dependency>
    <groupId>org.apache.bookkeeper</groupId>
    <artifactId>bookkeeper-server</artifactId>
    <version>4.16.5</version>
</dependency>

2、Ledger API

2.1、傳統 API

2.1.1、建立客戶端

public void createBookKeeper() throws Exception {
    ClientConfiguration configuration = new ClientConfiguration();
    configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.33:2181/ledgers");//單機
    //configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.30:2181;10.49.196.31:2181;10.49.196.32:2181/ledgers");//叢集
    configuration.setAddEntryTimeout(2000);
    bookKeeper = new BookKeeper(configuration);
}

2.1.2、建立 ledger 並新增 entry

//LedgerHandle ledgerHandle = bookKeeper.createLedger(3, 2, 2, BookKeeper.DigestType.MAC, "123".getBytes());
LedgerHandle ledgerHandle = bookKeeper.createLedger(BookKeeper.DigestType.MAC, "123".getBytes());
log.info("ledgerId={}", ledgerHandle.getId());
for (int i = 0; i < 10; i++) {
    long id = ledgerHandle.addEntry(("abc" + i).getBytes());
    log.info("id={}", id);
}

ledgerHandle.close();

建立 ledger 時可以指定儲存該 ledger 的節點個數、副本個數、幾個副本 ack 表示寫入成功。

2.1.3、從 ledger 中讀取 entry

public void readLedger() throws Exception {
    LedgerHandle ledgerHandle = bookKeeper.openLedger(0L, BookKeeper.DigestType.MAC, "123".getBytes());
    Enumeration<LedgerEntry> ledgerEntrys = ledgerHandle.readEntries(0, ledgerHandle.getLastAddConfirmed());
    while (ledgerEntrys.hasMoreElements()) {
        LedgerEntry ledgerEntry = ledgerEntrys.nextElement();
        log.info("ledgerId={},entryId={},entry={}", ledgerEntry.getLedgerId(), ledgerEntry.getEntryId(), new String(ledgerEntry.getEntry()));
    }

    ledgerHandle.close();
}

2.1.4、刪除 ledger

public void deleteLedger() throws Exception {
    bookKeeper.deleteLedger(0L);
}

2.1.5、完整程式碼

BookKeeper 介紹(3)--API
package com.abc.demo.bk;

import lombok.extern.slf4j.Slf4j;
import org.apache.bookkeeper.client.BookKeeper;
import org.apache.bookkeeper.client.LedgerEntry;
import org.apache.bookkeeper.client.LedgerHandle;
import org.apache.bookkeeper.conf.ClientConfiguration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Enumeration;


@Slf4j
public class LedgerCase {
    private BookKeeper bookKeeper;

    @Before
    public void createBookKeeper() throws Exception {
        ClientConfiguration configuration = new ClientConfiguration();
        //configuration.setZkServers("10.49.196.33:2181");
        configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.33:2181/ledgers");
        //configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.30:2181;10.49.196.31:2181;10.49.196.32:2181/ledgers");
        configuration.setAddEntryTimeout(2000);
        bookKeeper = new BookKeeper(configuration);
    }

    @After
    public void closeBookKeeper() throws Exception {
        bookKeeper.close();
    }

    @Test
    public void createLedger() throws Exception {
        //LedgerHandle ledgerHandle = bookKeeper.createLedger(3, 2, 2, BookKeeper.DigestType.MAC, "123".getBytes());
        LedgerHandle ledgerHandle = bookKeeper.createLedger(BookKeeper.DigestType.MAC, "123".getBytes());
        log.info("ledgerId={}", ledgerHandle.getId());
        for (int i = 0; i < 10; i++) {
            long id = ledgerHandle.addEntry(("abc" + i).getBytes());
            log.info("id={}", id);
        }

        ledgerHandle.close();
    }

    @Test
    public void readLedger() throws Exception {
        LedgerHandle ledgerHandle = bookKeeper.openLedger(0L, BookKeeper.DigestType.MAC, "123".getBytes());
        Enumeration<LedgerEntry> ledgerEntrys = ledgerHandle.readEntries(0, ledgerHandle.getLastAddConfirmed());
        while (ledgerEntrys.hasMoreElements()) {
            LedgerEntry ledgerEntry = ledgerEntrys.nextElement();
            log.info("ledgerId={},entryId={},entry={}", ledgerEntry.getLedgerId(), ledgerEntry.getEntryId(), new String(ledgerEntry.getEntry()));
        }

        ledgerHandle.close();
    }

    @Test
    public void deleteLedger() throws Exception {
        bookKeeper.deleteLedger(0L);
    }
}
LedgerCase.java

2.2、新 API

自 4.6 版本開始,BookKeeper 提供了一個新的客戶端 API,利用了Java 8 的 CompletableFuture 功能。引入了 WriteHandle、WriteAdvHandle 和 ReadHandle 來替換通用的 LedgerHandle。新的 API 在 org.apache.bookkeeper.client.api 包中,應該只使用該包中定義的介面。4.6 版本的新 API 仍然是實驗性的,並可能在後續的次要版本中進行更改。

2.2.1、建立客戶端

public void createBookKeeper() throws Exception {
    ClientConfiguration configuration = new ClientConfiguration();
    configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.33:2181/ledgers");//單機
    //configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.30:2181;10.49.196.31:2181;10.49.196.32:2181/ledgers");//叢集
    configuration.setAddEntryTimeout(2000);
    bookKeeper = BookKeeper
            .newBuilder(configuration)
            .build();
}

2.2.2、建立 ledger 並新增 entry

public void write() throws Exception {
    WriteHandle writeHandle = bookKeeper.newCreateLedgerOp()
            .withDigestType(DigestType.MAC)
            .withPassword("123".getBytes())
            .withEnsembleSize(3)
            .withWriteQuorumSize(3)
            .withAckQuorumSize(2)
            .execute()
            .get();
    log.info("ledgerId={}", writeHandle.getId());
    for (int i = 0; i < 10; i++) {
        long id = writeHandle.append(("bcd" + i).getBytes());
        log.info("id={}", id);
    }

    writeHandle.close();
}

2.2.3、從 ledger 中讀取 entry

public void read() throws Exception {
    ReadHandle readHandle = bookKeeper.newOpenLedgerOp()
            .withLedgerId(1L)
            .withDigestType(DigestType.MAC)
            .withPassword("123".getBytes())
            .execute()
            .get();

    LedgerEntries ledgerEntries = readHandle.read(0, readHandle.getLastAddConfirmed());
    Iterator<LedgerEntry> iterator = ledgerEntries.iterator();
    while (iterator.hasNext()) {
        LedgerEntry ledgerEntry = iterator.next();
        log.info("ledgerId={},entryId={},entry={}", ledgerEntry.getLedgerId(), ledgerEntry.getEntryId(), new String(ledgerEntry.getEntryBytes()));
    }

    readHandle.close();
}

2.2.4、刪除 ledger

public void delete() throws Exception {
   bookKeeper.newDeleteLedgerOp()
           .withLedgerId(101L)
           .execute()
           .get();
}

2.2.5、完整程式碼

BookKeeper 介紹(3)--API
package com.abc.demo.bk;

import lombok.extern.slf4j.Slf4j;
import org.apache.bookkeeper.client.api.*;
import org.apache.bookkeeper.conf.ClientConfiguration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Iterator;


@Slf4j
public class LedgerNewCase {
    private BookKeeper bookKeeper;

    @Before
    public void createBookKeeper() throws Exception {
        ClientConfiguration configuration = new ClientConfiguration();
        //configuration.setZkServers("10.49.196.33:2181");
        //configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.33:2181/ledgers");
        configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.30:2181;10.49.196.31:2181;10.49.196.32:2181/ledgers");
        configuration.setAddEntryTimeout(2000);
        bookKeeper = BookKeeper
                .newBuilder(configuration)
                .build();
    }

    @After
    public void closeBookKeeper() throws Exception {
        bookKeeper.close();
    }

    @Test
    public void write() throws Exception {
        WriteHandle writeHandle = bookKeeper.newCreateLedgerOp()
                .withDigestType(DigestType.MAC)
                .withPassword("123".getBytes())
                .withEnsembleSize(3)
                .withWriteQuorumSize(3)
                .withAckQuorumSize(2)
                .execute()
                .get();
        log.info("ledgerId={}", writeHandle.getId());
        for (int i = 0; i < 10; i++) {
            long id = writeHandle.append(("bcd" + i).getBytes());
            log.info("id={}", id);
        }

        writeHandle.close();
    }

    @Test
    public void read() throws Exception {
        ReadHandle readHandle = bookKeeper.newOpenLedgerOp()
                .withLedgerId(1L)
                .withDigestType(DigestType.MAC)
                .withPassword("123".getBytes())
                .execute()
                .get();

        LedgerEntries ledgerEntries = readHandle.read(0, readHandle.getLastAddConfirmed());
        Iterator<LedgerEntry> iterator = ledgerEntries.iterator();
        while (iterator.hasNext()) {
            LedgerEntry ledgerEntry = iterator.next();
            log.info("ledgerId={},entryId={},entry={}", ledgerEntry.getLedgerId(), ledgerEntry.getEntryId(), new String(ledgerEntry.getEntryBytes()));
        }

        readHandle.close();
    }

    @Test
    public void delete() throws Exception {
       bookKeeper.newDeleteLedgerOp()
               .withLedgerId(101L)
               .execute()
               .get();
    }
}
LedgerNewCase.java

3、Advanced Ledger API

在 4.5.0 版本中,BookKeeper 引入了一些高階 API 用於高階功能。高階 API 和普通 API 主要區別在寫 entry,讀 entry 是一致的。

3.1、LedgerHandleAdv

LedgerHandleAdv 是 LedgerHandle 的高階擴充套件,在建立時可以指定 LedgerId,在新增 entry 時需要傳入 entryId。

public void ledgerHandleAdv() throws Exception {
    ClientConfiguration configuration = new ClientConfiguration();
    //configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.33:2181/ledgers");
    configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.30:2181;10.49.196.31:2181;10.49.196.32:2181/ledgers");
    configuration.setAddEntryTimeout(2000);
    org.apache.bookkeeper.client.BookKeeper bookKeeper = new org.apache.bookkeeper.client.BookKeeper(configuration);

    //LedgerHandleAdv ledgerHandle = (LedgerHandleAdv) bookKeeper.createLedgerAdv(3, 2, 2, BookKeeper.DigestType.MAC, "123".getBytes());
    LedgerHandleAdv ledgerHandleAdv = (LedgerHandleAdv) bookKeeper.createLedgerAdv(100L, 3, 2, 2, org.apache.bookkeeper.client.BookKeeper.DigestType.MAC, "123".getBytes(), Collections.emptyMap());

    log.info("ledgerId={}", ledgerHandleAdv.getId());
    for (int i = 0; i < 10; i++) {
        long id = ledgerHandleAdv.addEntry(i, ("abc" + i).getBytes()); //entry id 需從 0 開始
        log.info("id={}", id);
    }

    ledgerHandleAdv.close();
    bookKeeper.close();
}

3.2、4.6 版本新 API 的 LedgerHandleAdv

public void writeAdvHandle() throws Exception {
    ClientConfiguration configuration = new ClientConfiguration();
    //configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.33:2181/ledgers");
    configuration.setMetadataServiceUri("zk+hierarchical://10.49.196.30:2181;10.49.196.31:2181;10.49.196.32:2181/ledgers");

    org.apache.bookkeeper.client.api.BookKeeper bookKeeper = org.apache.bookkeeper.client.api.BookKeeper
            .newBuilder(configuration)
            .build();
    WriteAdvHandle writeAdvHandle = bookKeeper.newCreateLedgerOp()
            .withDigestType(DigestType.MAC)
            .withPassword("123".getBytes())
            .withEnsembleSize(3)
            .withWriteQuorumSize(3)
            .withAckQuorumSize(2)
            .makeAdv() //CreateBuilder 轉為 CreateAdvBuilder
            .withLedgerId(101L)
            .execute()
            .get();
    log.info("ledgerId={}", writeAdvHandle.getId());
    for (int i = 0; i < 10; i++) {
        long id = writeAdvHandle.write(i, ("bcd" + i).getBytes());
        log.info("id={}", id);
    }

    writeAdvHandle.close();
    bookKeeper.close();
}

參考:
https://bookkeeper.apache.org/docs/api/overview

相關文章