【Hbase】hbase使用juicefs对象存储测试环境快速部署
相关技术链接:
juicefs 官方部署参考文档
移动云使用 JuiceFS 支持 Apache HBase 增效降本的探索
如何让 HBase 更快、更稳、更省钱
0 前言
什么是juicefs
详情请看官网介绍:https://www.juicefs.com/docs/zh/community/introduction/
关于hbase
Apache HBase 是 Apache Hadoop 生态体系中的大规模、可扩展、分布式的数据存储服务。同时它还是 NoSQL 数据库。它的设计初衷是为包含了数百万列的数十亿行记录提供随机的、强一致性的实时查询。
默认情况下,HBase 的数据会保存在 HDFS 上,HBase 为 HDFS 做了很多优化来保证稳定性与性能。但是维护 HDFS 本身一点也不轻松,要不断进行监控、运维、调优、扩容、灾难恢复等一系列事情。
最近了解到juicefs 一款面向云原生设计的高性能共享文件系统,仿佛带来了一些新的体验,比较好奇的是:
- hbase基于hadoop,应用对象存储难不难
- hbase基于juicefs的存算分离模式,性能怎么样
- 是不是真的能减轻运维压力
这里先简单上手,以搭建一个以对象存储的hbase环境为目的,先验证下第一个问题。
技术选型及架构表示如下:
1 元数据库-reids
https://hub.docker.com/r/bitnami/redis
# 拉镜像
docker pull bitnami/redis:7.0
# 运行redis server
docker run -d -p 6379:6379 --name redis-server \
-d -e ALLOW_EMPTY_PASSWORD=yes \
-v /home/hadoop/jiazz/volume/redis/data:/bitnami/redis/data \
bitnami/redis:7.0
# redis client连接
docker run -it --link redis-server:redis-server --rm bitnami/redis:7.0 redis-cli -h redis-server
2 对象存储--minio
这里选择minio作为对象存储,可以选择官方的,也可以选择bitnami的
注意事项:
- 服务端用户名称>=5位
- 服务端用户密码>=8位
- 容器间主机名称不能识别,可通过--link
- 确认自己服务端口,写错或者默认值都可能连不上的
bitnami/minio
https://hub.docker.com/r/bitnami/minio
# 拉镜像
docker pull bitnami/minio:2022.8.11
docker pull bitnami/minio-client:2022.8.11
docker run --name minio-server -d \
--publish 9000:9000 \
--publish 9001:9001 \
--env MINIO_ROOT_USER="minio-root-user" \
--env MINIO_ROOT_PASSWORD="minio-root-password" \
bitnami/minio:2022.8.11
docker run -it --link minio-server:minio-server --rm --name minio-client \
--env MINIO_SERVER_HOST="minio-server" \
--env MINIO_SERVER_ACCESS_KEY="minio-root-user" \
--env MINIO_SERVER_SECRET_KEY="minio-root-password" \
bitnami/minio-client:2022.8.11 \
mb minio/my-bucket
minio/minio
https://min.io/download#/docker
docker pull --platform=linux/amd64 minio/minio
docker pull --platform=linux/amd64 minio/mc
# MINIO SERVER 用户名长度>=5位,密码长度>=8位
docker run -d --name minio-server \
--env MINIO_SERVER_HOST="minio-server" \
--env MINIO_SERVER_ACCESS_KEY="minioadmin" \
--env MINIO_SERVER_SECRET_KEY="minioadmin" \
-v /home/hadoop/jiazz/volume/minio/data:/data \
-v /home/hadoop/jiazz/volume/minio/config:/root/.minio \
-p 9000:9000 -p 39001:9001 minio/minio server /data --console-address ":9001"
# MINIO CLIENT
docker run --name my-mc --hostname my-mc --link minio-server:minio-server -it --entrypoint /bin/bash --rm minio/mc
[root@my-mc /]# mc alias set myminio/ http://minio-server:9000 minioadmin minioadmin
Added `myminio` successfully.
[root@my-mc /]# mc ls myminio/
浏览器访问:http://test002:39001/buckets
报错示例一:secret key长度需要>=8
[root@my-mc /]# mc alias set myminio/ https://minio-server admin 123456
mc: Configuration written to `/root/.mc/config.json`. Please update your access credentials.
mc: Successfully created `/root/.mc/share`.
mc: Initialized share uploads `/root/.mc/share/uploads.json` file.
mc: Initialized share downloads `/root/.mc/share/downloads.json` file.
mc: <ERROR> Invalid secret key `123456`. Invalid arguments provided, please refer `mc <command> -h` for relevant documentation.
报错示例二:minio server host port 需要指定
默认:http 是80端口,https是443端口
而minio服务是9000端口
# mc alias set myminio/ https://minio-server minioadmin minioadmin
mc: Configuration written to `/root/.mc/config.json`. Please update your access credentials.
mc: Successfully created `/root/.mc/share`.
mc: Initialized share uploads `/root/.mc/share/uploads.json` file.
mc: Initialized share downloads `/root/.mc/share/downloads.json` file.
mc: <ERROR> Unable to initialize new alias from the provided credentials. Get "https://minio-server": dial tcp 172.17.0.3:443: connect: connection refused.
3 juicefs 单机部署
客户端安装
这里是在linux主机上安装 https://juicefs.com/docs/zh/community/installation#linux-%E5%8F%91%E8%A1%8C%E7%89%88
以 x86 架构的 Linux 系统为例,下载文件名包含 linux-amd64 的压缩包,在终端依次执行以下命令。
1. 获取最新的版本号
JFS_LATEST_TAG=$(curl -s https://api.github.com/repos/juicedata/juicefs/releases/latest | grep 'tag_name' | cut -d '"' -f 4 | tr -d 'v')
2. 下载客户端到当前目录
wget "https://github.com/juicedata/juicefs/releases/download/v${JFS_LATEST_TAG}/juicefs-${JFS_LATEST_TAG}-linux-amd64.tar.gz"
3. 解压安装包
tar -zxf "juicefs-${JFS_LATEST_TAG}-linux-amd64.tar.gz"
4. 安装客户端
sudo install juicefs /usr/local/bin
5. 完成上述 4 个步骤,在终端执行 juicefs 命令,返回帮助信息,则说明客户端安装成功。
创建文件系统
juicefs format[command options] META-URL NAME
可见,格式化文件系统需要提供 3 种信息:
- [command options]:设定文件系统的存储介质,留空则默认使用本地磁盘作为存储介质,路径为 "$HOME/.juicefs/local","/var/jfs" 或 "C:/jfs/local";
- META-URL:用来设置元数据存储,即数据库相关的信息,通常是数据库的 URL 或文件路径;
- NAME:是文件系统的名称。
# 这里注意如果之前format过,使用的storage不同,再次format会失败,清理一下数据库再重新format
# 如redis,flushall一下缓存
$ juicefs format \
--storage minio \
--bucket http://127.0.0.1:9000/myjfs \
--access-key minioadmin \
--secret-key minioadmin \
redis://192.168.1.6:6379/1 \
myjfs
2022/08/17 18:50:54.992039 juicefs[7570] <INFO>: Meta address: redis://192.168.1.6:6379/1 [interface.go:402]
2022/08/17 18:50:54.995366 juicefs[7570] <INFO>: Ping redis: 59.118µs [redis.go:2878]
2022/08/17 18:50:54.995859 juicefs[7570] <INFO>: Data use minio://127.0.0.1:9000/myjfs/myjfs/ [format.go:435]
2022/08/17 18:50:55.009169 juicefs[7570] <INFO>: Volume is formatted as {
"Name": "myjfs",
"UUID": "d912f805-cbf3-412e-bcc4-bbbc5c2584c4",
"Storage": "minio",
"Bucket": "http://127.0.0.1:9000/myjfs",
"AccessKey": "minQioadmin",
"SecretKey": "removed",
"BlockSize": 4096,
"Compression": "none",
"KeyEncrypted": true,
"TrashDays": 1,
"MetaVersion": 1
} [format.go:472]
# 从输出的信息知道我们创建了一个文件系统叫myjfs,他的存储介质是minio,buckeyt为http://127.0.0.1:9000/myjfs
可以挂载一下,方便查看,这里就不挂载了
3 hadoop
sdk部署
下载 JuiceFS Hadoop Java SDK,当前最新稳定版本为v1.0.0
cp juicefs-hadoop-1.0.0.jar ${HADOOP_HOME}/share/hadoop/common/
core-site.xml 配置
<property>
<name>fs.jfs.impl</name>
<value>io.juicefs.JuiceFileSystem</value>
</property>
<property>
<name>fs.AbstractFileSystem.jfs.impl</name>
<value>io.juicefs.JuiceFS</value>
</property>
<property>
<name>juicefs.meta</name>
<value>redis://{HOST}:{PORT}/{DB}</value>
<!--demo <value>redis://127.0.0.1:6379/1</value> -->
</property>
<property>
<name>juicefs.cache-dir</name>
<value>/data*/jfs</value>
</property>
<property>
<name>juicefs.cache-size</name>
<value>1024</value>
</property>
<property>
<name>juicefs.access-log</name>
<value>/tmp/juicefs.access.log</value>
</property>
测试是否部署成功
hadoop fs -ls jfs://{JFS_NAME}/
$ hdfs dfs -put README.md jfs://myjfs/
$ hadoop fs -ls jfs://myjfs/
Found 1 items
-rw-r--r-- 1 hadoop supergroup 14163 2022-08-18 14:41 jfs://myjfs/README.md
$ hadoop fs -tail jfs://myjfs/README.md
pported-object-storage) first. If the object storage you want to use is compatible with S3, you could treat it as S3. Otherwise, try reporting issue.
### Can I use Redis Cluster as metadata engine?
Yes. Since [v1.0.0 Beta3](https://github.com/juicedata/juicefs/releases/tag/v1.0.0-beta3) JuiceFS supports the use of [Redis Cluster](https://redis.io/docs/manual/scaling) as the metadata engine, but it should be noted that Redis Cluster requires that the keys of all operations in a transaction must be in the same hash slot, so a JuiceFS file system can only use one hash slot.
See ["Redis Best Practices"](docs/en/administration/metadata/redis_best_practices.md) for more information.
### What's the difference between JuiceFS and XXX?
See ["Comparison with Others"](docs/en/introduction/comparison) for more information.
For more FAQs, please see the [full list](docs/en/faq.md).
## Stargazers over time
[![Stargazers over time](https://starchart.cc/juicedata/juicefs.svg)](https://starchart.cc/juicedata/juicefs)
# 不指定jfs,默认还是hdfs
$ hdfs dfs -ls /
Found 5 items
drwxr-xr-x - hbase supergroup 0 2022-08-17 16:37 /hbase
drwxr-xr-x - hadoop supergroup 0 2022-08-18 14:59 /hbase-wal-jfs
drwxr-xr-x - hadoop supergroup 0 2022-06-27 16:10 /test
drwxr-xr-x - hadoop supergroup 0 2022-06-27 16:55 /tmp
drwx------ - hadoop supergroup 0 2022-06-27 16:05 /user
问题处理:如时报如下错误是因为dfs.blocksize的配置使用了256m,juicefs不支持使用单位表示,需要改成268435456表示形式
$ hdfs dfs -ls jfs://myjfs
-ls: For input string: "256m"
4 hbase
JuiceFS 适合存储 HBase 的 HFile,但不适合用来保存它的事务日志(WAL),因为将日志持久化到对象存储的时间会远高于持久化到 HDFS 的 DataNode 的内存中。
建议部署一个小的 HDFS 集群来存放 WAL,HFile 文件则存储在 JuiceFS 上。
hbase-site.xml
<property>
<name>hbase.rootdir</name>
<value>jfs://{vol_name}/hbase</value>
<!-- demo <value>jfs://myjfs/hbase</value>-->
</property>
<property>
<name>hbase.wal.dir</name>
<value>hdfs://{ns}/hbase-wal</value>
<!--<value>hdfs://test:8020/hbase-wal-jfs</value>-->
</property>
创建目录
# 创建jfs目录,存放data
hdfs dfs -mkdir jfs://myjfs/hbase
# 创建hdfs目录,存储wal
hdfs dfs -mkdir /hbase-wal
修改原有hbase集群
除了修改上述配置项外,由于 HBase 集群已经在 ZooKeeper 里存储了部分数据,为了避免冲突,有以下两种方式解决:
- 删除原集群通过 ZooKeeper 客户端删除
zookeeper.znode.parent
配置的 znode(默认 /hbase)。注意此操作将会删除原有 HBase 上面的所有数据 - 使用新的 znode保留原 HBase 集群的 znode,以便后续可以恢复。然后为
zookeeper.znode.parent
配置一个新的值:
<property>
<name>zookeeper.znode.parent</name>
<value>/hbase-jfs</value>
</property>
这里选择方式二
测试部署是否成功
$ hbase shell
hbase(main):004:0> create 'jfstest1','f'
Created table jfstest1
Took 0.8027 seconds
=> Hbase::Table - jfstest1
hbase(main):008:0> put 'jfstest1','r1','f:c','v1'
Took 0.1812 seconds
hbase(main):009:0> scan 'jfstest1'
ROW COLUMN+CELL
r1 column=f:c, timestamp=1660806491549, value=v1
1 row(s)
Took 0.0284 seconds
ycsb测试一把
由于该环境只是一个简单的单机环境,只简单跑一下,不以压测为目的。后续搭建一个分布式环境认真测试一下。
hbase(main):001:0> n_splits = 40 # HBase recommends (10 * number of regionservers)
hbase(main):002:0> create 'usertable', 'family', {SPLITS => (1..n_splits).map {|i| "user#{1000+i*(9999-1000)/n_splits}"}}
# 大概1.42G数据
./bin/ycsb load hbase20 -P workloads/workloada -cp ~/cloud/hbase/conf -p table=usertable -p columnfamily=family -p recordcount=1000000 -p operationcount=1000000 -threads 5 -s
看一下minio中jfs数据是什么样的:
任何存入 JuiceFS 的文件都会被拆分成固定大小的 "Chunk",默认的容量上限是 64 MiB。每个 Chunk 由一个或多个 "Slice" 组成,Slice 的长度不固定,取决于文件写入的方式。每个 Slice 又会被进一步拆分成固定大小的 "Block",默认为 4 MiB。最后,这些 Block 会被存储到对象存储。与此同时,JuiceFS 会将每个文件以及它的 Chunks、Slices、Blocks 等元数据信息存储在元数据引擎中。