Apache BookKeeper是什么
Apache BookKeeper是一种可扩容、容错、低延迟的存储服务,针对实时工作负载进行了优化,并提供持久性、可复制性和强一致性作为构建可靠实时应用程序的必要条件。
BookKeeper 各种实例使用场景:
| Use Case | Example |
|---|---|
| WAL(write-ahead logging) | The HDFS namenode |
| WAL(write-ahead logging) | Twitter Manhattan |
| WAL(write-ahead logging) | HerdDB |
| Message storage | Apache Pulsar |
| Offset/cursor storage | Apache Pulsar |
| Object/BLOB storage | Storing snapshots to replicated state machines |
笔者记录时Release的版本为4.15.0
运行环境为VMvare 上运行的CentOS 7,Java为OpenJDK 11
[root@localhost bookkeeper3]# java -version
openjdk version "11.0.15" 2022-04-19 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.15+9-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.15+9-LTS, mixed mode, sharing)
下载bookkeeper到CentOS
wget https://dlcdn.apache.org/bookkeeper/bookkeeper-4.15.0/bookkeeper-server-4.15.0-bin.tar.gz
解压并重命名为bookeeper
--strip-components N 表示删除目录结构(n=1表示删除最外【或前1】层结构)
mkdir ~/bookkeeper && tar -zxvf bookkeeper-server-4.15.0-bin.tar.gz -C ~/bookkeeper --strip-components 1
此时~目录下就有bookkeeper文件夹。
要想运行bookkepper集群,首先要搭建zookeeper,因为bookkepper的元数据就是存储在zookeeper集群中。
为了演示我只运行了一台zookeeper,zookeeper集群请自行查阅资料搭建。
下载zookeeper并解压到~目录下为apache-zookeeper.
cd apache-zookeeper
#创建数据目录和logs目录
mkdir -p data logs
cd conf
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
#修改数据目录和日志目录
dataDir=/root/apache-zookeeper/data
dataLogDir=/root/apache-zookeeper/logs
退出保存
sh bin/zkServer.sh start #后台运行
sh bin/zkServer.sh start-foreground #前台运行
binding to port 0.0.0.0/0.0.0.0:2181 说明zookeeper运行正常。
下面修改三台bookeeper配置。
cp bookkeeper bookkeeper1 bookkeeper2 bookkeeper3
rm -rf bookkeeper
cd bookkeeper1
vim conf/bk_server.conf
#修改以下这些参数
#############################################################################
## Server parameters
#############################################################################
bookiePort=3181
advertisedAddress=192.168.236.188 #为centos7的IP地址
extraServerComponents=
#############################################################################
## server settings
#############################################################################
httpServerEnabled=false
httpServerPort=8181
httpServerClass=org.apache.bookkeeper.http.vertx.VertxHttpServer
############################################## Bookie Storage ##############################################
#############################################################################
## Journal settings
#############################################################################
journalDirectories=/tmp/bk1-txn
#############################################################################
## Ledger storage settings
#############################################################################
ledgerDirectories=/tmp/bk1-data
indexDirectories=/tmp/bk1-data
############################################## Metadata Services ##############################################
#############################################################################
## Metadata Service settings
#############################################################################
metadataServiceUri=zk+hierarchical://192.168.236.188:2181/ledgers
#############################################################################
## ZooKeeper Metadata Service settings
#############################################################################
zkServers=192.168.236.188:2181
zkTimeout=10000
zkEnableSecurity=false
##################################################################
##################################################################
# Settings below are used by stream/table service
##################################################################
##################################################################
### Grpc Server ###
storageserver.grpc.port=4181
### Dlog Settings for table service ###
#### Replication Settings
dlog.bkcEnsembleSize=3
dlog.bkcWriteQuorumSize=2
dlog.bkcAckQuorumSize=2
### Storage ###
# local storage directories for storing table ranges data (e.g. rocksdb sst files)
storage.range.store.dirs=/tmp/bookkeeper1/ranges
# whether the storage server capable of serving readonly tables. default is false.
storage.serve.readonly.tables=false
# the cluster controller schedule interval, in milliseconds. default is 30 seconds.
storage.cluster.controller.schedule.interval.ms=30000
由于在同一台机器运行bookkeeper,所以需要将bookkeeper2,bookkeeper3的端口号修改一下
bookeeper2
#修改以下这些参数
#############################################################################
## Server parameters
#############################################################################
bookiePort=3182
advertisedAddress=192.168.236.188 #为centos7的IP地址
extraServerComponents=
#############################################################################
## server settings
#############################################################################
httpServerEnabled=false
httpServerPort=8182
httpServerClass=org.apache.bookkeeper.http.vertx.VertxHttpServer
############################################## Bookie Storage ##############################################
#############################################################################
## Journal settings
#############################################################################
journalDirectories=/tmp/bk2-txn
#############################################################################
## Ledger storage settings
#############################################################################
ledgerDirectories=/tmp/bk2-data
indexDirectories=/tmp/bk2-data
############################################## Metadata Services ##############################################
#############################################################################
## Metadata Service settings
#############################################################################
metadataServiceUri=zk+hierarchical://192.168.236.188:2181/ledgers
#############################################################################
## ZooKeeper Metadata Service settings
#############################################################################
zkServers=192.168.236.188:2181
zkTimeout=10000
zkEnableSecurity=false
##################################################################
##################################################################
# Settings below are used by stream/table service
##################################################################
##################################################################
### Grpc Server ###
storageserver.grpc.port=4181
### Dlog Settings for table service ###
#### Replication Settings
dlog.bkcEnsembleSize=3
dlog.bkcWriteQuorumSize=2
dlog.bkcAckQuorumSize=2
### Storage ###
# local storage directories for storing table ranges data (e.g. rocksdb sst files)
storage.range.store.dirs=/tmp/bookkeeper2/ranges
# whether the storage server capable of serving readonly tables. default is false.
storage.serve.readonly.tables=false
# the cluster controller schedule interval, in milliseconds. default is 30 seconds.
storage.cluster.controller.schedule.interval.ms=30000
bookkeeper3
#修改以下这些参数
#############################################################################
## Server parameters
#############################################################################
bookiePort=3183
advertisedAddress=192.168.236.188 #为centos7的IP地址
extraServerComponents=
#############################################################################
## server settings
#############################################################################
httpServerEnabled=false
httpServerPort=8183
httpServerClass=org.apache.bookkeeper.http.vertx.VertxHttpServer
############################################## Bookie Storage ##############################################
#############################################################################
## Journal settings
#############################################################################
journalDirectories=/tmp/bk3-txn
#############################################################################
## Ledger storage settings
#############################################################################
ledgerDirectories=/tmp/bk3-data
indexDirectories=/tmp/bk3-data
############################################## Metadata Services ##############################################
#############################################################################
## Metadata Service settings
#############################################################################
metadataServiceUri=zk+hierarchical://192.168.236.188:2181/ledgers
#############################################################################
## ZooKeeper Metadata Service settings
#############################################################################
zkServers=192.168.236.188:2181
zkTimeout=10000
zkEnableSecurity=false
##################################################################
##################################################################
# Settings below are used by stream/table service
##################################################################
##################################################################
### Grpc Server ###
storageserver.grpc.port=4181
### Dlog Settings for table service ###
#### Replication Settings
dlog.bkcEnsembleSize=3
dlog.bkcWriteQuorumSize=2
dlog.bkcAckQuorumSize=2
### Storage ###
# local storage directories for storing table ranges data (e.g. rocksdb sst files)
storage.range.store.dirs=/tmp/bookkeeper3/ranges
# whether the storage server capable of serving readonly tables. default is false.
storage.serve.readonly.tables=false
# the cluster controller schedule interval, in milliseconds. default is 30 seconds.
storage.cluster.controller.schedule.interval.ms=30000
到这里三台bookkeeper配置完成。 我们可以通过集群中任何一台bookie中运行下面命令来为集群设置集群元数据:
cd ~/bookkeeper1
sh bin/bookkeeper shell metaformat
一旦集群元数据格式化完成,你的BookKeeper集群就准备好了。
开始启动bookkeeper集群
sh ~/bookkeeper1/bin/bookkeeper bookie
sh ~/bookkeeper2/bin/bookkeeper bookie
sh ~/bookkeeper3/bin/bookkeeper bookie
INFO org.apache.bookkeeper.common.component.ComponentStarter - Started component bookie-server.
#出现这句话说明bookie server 启动成功。
此时我们使用IDEA构建一个java客户端来进行测试消息。
引入依赖项
<dependency>
<groupId>org.apache.bookkeeper</groupId>
<artifactId>bookkeeper-server</artifactId>
<version>4.15.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.bookkeeper</groupId>
<artifactId>bookkeeper-common</artifactId>
<version>4.15.0</version>
<scope>test</scope>
</dependency>
客户端API测试代码如下:
public class Test {
public static final String GISONWIN = "gisonwin";
public static final String ZK_SERVER = "zk+hierarchical://192.168.236.188/ledgers";
public static final int CONNECT_TIMEOUT_MILLIS = 3000000;
static void test2() {
try {
ClientConfiguration config = new ClientConfiguration();
config.setMetadataServiceUri(ZK_SERVER);
config.setTimeoutMonitorIntervalSec(CONNECT_TIMEOUT_MILLIS);
org.apache.bookkeeper.client.api.BookKeeper bkClient = org.apache.bookkeeper.client.api.BookKeeper.newBuilder(config).build();
System.out.println("BookKeeper client init success.");
WriteHandle writeHandle = bkClient.newCreateLedgerOp().withDigestType(org.apache.bookkeeper.client.api.DigestType.MAC).withPassword(GISONWIN.getBytes()).execute().get();
for (int i = 0; i < 10; i++) {
byte[] data = new String(GISONWIN + ":message-" + i).getBytes();
writeHandle.append(data);
System.out.println("write to ==> " + new String(data));
}
writeHandle.close();
long ledgerId = writeHandle.getLedgerMetadata().getLedgerId();
ReadHandle readHandle = bkClient.newOpenLedgerOp().withLedgerId(ledgerId).withDigestType(org.apache.bookkeeper.client.api.DigestType.MAC).withPassword(GISONWIN.getBytes()).execute().get();
System.out.println("ledgerId = " + ledgerId);
Iterator<org.apache.bookkeeper.client.api.LedgerEntry> iterable = readHandle.read(0, writeHandle.getLastAddConfirmed()).iterator();
while (iterable.hasNext()) {
org.apache.bookkeeper.client.api.LedgerEntry entry = iterable.next();
System.out.println("read => " + new String(entry.getEntryBytes()));
}
readHandle.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
test2();
}
}
测试代码在windows10下运行。
read => gisonwin:message-0
read => gisonwin:message-1
read => gisonwin:message-2
read => gisonwin:message-3
read => gisonwin:message-4
read => gisonwin:message-5
read => gisonwin:message-6
read => gisonwin:message-7
read => gisonwin:message-8
read => gisonwin:message-9
#说明消息存储成功并读取成功
服务器上截图
bookkeeper1
bookeeper2
bookeeper3
写在最后:
遇到的问题
1.客户端代码 API连接集群时一直在报错误: ConnectionLossException: KeeperErrorCode = ConnectionLoss
解决方案: windows下将192.168.236.188添加到hosts文件中。
192.168.236.188 localhost.localdomain
#后面是192.168.236.188对应的hostname
2.bookie重启后会报一个instanceID不匹配,这个情况是将zookeeper重启后会遇到
我的解决方案简单粗暴:
zookeeper重启后,使用任意一个bookeeper上面进行元数据重新格式化
sh bin/bookkeeper shell metaformat
然后将/tmp/bk1-* bk2-* bk3-* 数据全部删掉。