首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

  • 24-12-06 05:45
  • 4703
  • 19665
juejin.cn

Go-Rocksdb开发环境搭建

因为需要使用golang开发rocksdb,其中有不少繁琐的环境依赖,所以记录一下mac上的开发环境搭建,并提供dockerfile以便在window或者liunx环境下使用。

注意,当前环境:(不是这个环境可能不适用)

yaml
代码解读
复制代码
go: 1.21 rocksdb: 7.10.2 lunxGnu/grocksdb: 1.7.16 < macOs: 13 >

环境介绍

  • rocksdb是facebook开源的一个kv数据库,经常作为存储中心的前置引擎。由C++编写,支持通过 C 绑定嵌入到使用 C、C++、Rust、Go 和 Java 等多种语言编写的应用程序中。

  • rocksdb运行时依赖于多个软件包,需要在对应系统安装。

    dart
    代码解读
    复制代码
    You can link RocksDB with following compression libraries: zlib - a library for data compression. bzip2 - a library for data compression. lz4 - a library for extremely fast data compression. snappy - a library for fast data compression. zstandard - Fast real-time compression algorithm. All our tools depend on: gflags - a library that handles command line flags processing. You can compile rocksdb library even if you don't have gflags installed.
  • rocksdb的编译有多种选择,可以是编译静态库,也可以编译动态库,基于开发架构选择使用。

    go
    代码解读
    复制代码
    make clean 静态库编译,得到librocksdb.a文件 make static_lib or 动态库编译,得到librocksdb.dylib(mac)或者librocksdb.so(linux)文件 make shared_lib or cmake 编译 mkdir ./build && cd ./build cmake .. make 安装 make install shared PREFIX="路径"
  • CGO环境,使用golang开发rocksdb,通过cgo与rocksdb通讯,需要配置对应的环境。go env的CGO_ENABLED='1'

    golang
    代码解读
    复制代码
    指定rocksdb的include,可以使用源代码项目中的,也可以install export CGO_CFLAGS="-I/Users/apple/workspace/rocksdb_env/include" 指定链接库,rocksdb可以是动态库或者静态库,其他的是对应的依赖 export CGO_LDFLAGS="-L/Users/apple/workspace/rocksdb_env -lrocksdb -lstdc++ -lm -lz -lsnappy -llz4 -lzstd"
  • 指定动态库路径查找路径,程序会到usr/lib,/usr/local/lib等路径中查找,可以通过参数控制。

    bash
    代码解读
    复制代码
    liunx中 export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH mac中 export DYLD_LIBRARY_PATH="/usr/local/lib:$DYLD_LIBRARY_PATH"
  • lunxGnu/grocksdb 包装了rocksdb的接口,方便golang开发者使用


mac安装

  • 通过brew安装rocksdb的依赖(注意版本,经过测试,macOs 14安装的版本并不适用,需要手动通过源码编译)

    sql
    代码解读
    复制代码
    brew install zlib bzip2 lz4 snappy zstd ---- 注意版本: librocksdb.dylib: @rpath/librocksdb.7.dylib (compatibility version 7.0.0, current version 7.10.2) /opt/homebrew/opt/gflags/lib/libgflags.2.2.dylib (compatibility version 2.2.0, current version 2.2.2) /opt/homebrew/opt/zstd/lib/libzstd.1.dylib (compatibility version 1.0.0, current version 1.5.5) /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1300.36.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
  • 下载rocksdb源码: git clone github.com/facebook/ro… && git checkout tags/v7.10.2​

  • make编译

    • 这里需要注意gcc的版本,有可能执行make失败,自行解决 :)。

    • make执行不了就通过cmake编译,cmake编译需要注意一个坑:

      scala
      代码解读
      复制代码
      如果开发对应的rocksdb中使用了zstd压缩,指定了zstd的压缩算法,那么需要将zstd的依赖编译进rocksdb的动态链接库librocksdb.dylib中。若没有将zstd编译进来,编译go_rocksdb程序能够成功。但是会在运行go程序的时候报错: `Invalid argument: Compression type ZSTD is not linked with the binary`。 坑点: 在rocksdb7.10.2的分支中,cmake对应的CMakeLists.txt文件却默认把zstd依赖关掉了,导致了cmake编译出来的动态库是不包含zstd依赖的。 解决: 把CMakeLists.txt中,option(WITH_ZSTD "build with zstd" OFF) 的OFF改成ON,就可以将zstd编译到动态库中,golang调用cgo的时候可以找到zstd。
  • 静态库与动态库的选择,两者二选一,只要设定好CGO_LDFLAGS路径即可。不过使用动态库的话,需要关注LD_LIBRARY_PATH(linux)参数。

  • make intall 安装

  • 检查,如果使用动态库的话,确保动态库依赖都装上了。

    sql
    代码解读
    复制代码
    otool -L librocksdb.dylib librocksdb.dylib: @rpath/librocksdb.7.dylib (compatibility version 7.0.0, current version 7.10.2) /opt/homebrew/opt/gflags/lib/libgflags.2.2.dylib (compatibility version 2.2.0, current version 2.2.2) /opt/homebrew/opt/zstd/lib/libzstd.1.dylib (compatibility version 1.0.0, current version 1.5.5) /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1300.36.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
  • 编译与运行


Docker 开箱即用

如果不是在mac上,可以使用docker打包环境,在docker容器中开发。最好选择liunx docker环境。

  • 提供dockerfile,基于alpine liunx编译rocksdb与对应依赖,然后拷贝到golang1.21的alpine环境中使用,确保开箱即用。
  • 官方golang1.21-alpine基于alpine3.20, 版本相对较高,需要做对应的修改。
  • alpine3.20的国内软件源需要使用对应的版本。
  • 将开发目录挂载进入docker中,使用vscode远程连接进入docker中开发。(确保与主机桥接网络,避免内部依赖拉取不了)

Dockerfile

bash
代码解读
复制代码
FROM alpine:3.20 AS builder ARG ROCKSDB_VERSION=v7.10.2 ARG LIB_DIR=/usr/local/rocksdb_env RUN echo -e http://mirrors.ustc.edu.cn/alpine/v3.20/main/ > /etc/apk/repositories RUN apk update && \ apk add --no-cache --update \ build-base \ autoconf \ automake \ libtool \ pkgconfig \ git \ bash \ linux-headers \ perl RUN apk add --no-cache --update \ zlib-dev \ snappy-dev \ bzip2-dev \ lz4-dev \ zstd-dev \ zstd \ libcurl \ curl-dev \ libsodium-dev RUN apk add --no-cache --update cmake RUN cd /tmp && \ git clone https://github.com/gflags/gflags.git && \ cd gflags && \ mkdir build && \ cd build && \ cmake -DBUILD_SHARED_LIBS=1 -DGFLAGS_INSTALL_SHARED_LIBS=1 .. && \ make install && \ cd /tmp && \ rm -R /tmp/gflags/ RUN mkdir /usr/src && \ cd /usr/src && \ git clone --depth 1 --branch ${ROCKSDB_VERSION} https://github.com/facebook/rocksdb.git && \ cd /usr/src/rocksdb RUN gcc --version && \ echo "rocksdb_version= ${ROCKSDB_VERSION}" # - 编译rocksdb动态库,因为alpine liunx安装的软件都是默认动态库,所以依赖也都是动态库. # - 因为alpine liunx 3.20中,gcc版本与rocksdb v7.10.2不同, # 所以需要手动添加 cstdint 头文件,否则编译失败. # - 因为alpine基于busybox,musl与gnu有的命令有区别,所以需要修改makfile中的install的选项。 RUN cd /usr/src/rocksdb && \ sed -i '1i #include ' table/block_based/data_block_hash_index.h && \ sed -i '1i #include ' util/string_util.h && \ sed -i 's/install -C/install -c/g' Makefile RUN cd /usr/src/rocksdb && \ make clean && \ # make shared_lib && \ echo "rocksdb_lib= ${LIB_DIR}" && \ make install-shared PREFIX=${LIB_DIR} && \ cd ${LIB_DIR}/lib && \ # rm -R /usr/src/rocksdb/ && \ ls -al && \ ldd ./librocksdb.so # ---------------------------------------------------------- FROM golang:1.21-alpine ARG ROCKSDB_VERSION=v7.10.2 ARG LIB_DIR=/usr/local/rocksdb_env RUN mkdir -p ${LIB_DIR} &&\ mkdir -p /app && \ echo -e http://mirrors.ustc.edu.cn/alpine/v3.20/main/ > /etc/apk/repositories # 复制编译好的 RocksDB 到最终镜像 COPY --from=builder /usr/local/lib /usr/local/lib COPY --from=builder /usr/lib /usr/lib COPY --from=builder ${LIB_DIR} ${LIB_DIR} # COPY --from=builder /usr/local/include/rocksdb /usr/local/include/rocksdb # 设置CGO环境变量 ENV CGO_CFLAGS="-I${LIB_DIR}/include" \ CGO_LDFLAGS="-L${LIB_DIR}/lib -lrocksdb -lstdc++ -lm -lz -lsnappy -llz4 -lzstd" \ LD_LIBRARY_PATH="/usr/local/lib:${LIB_DIR}/lib:$LD_LIBRARY_PATH" \ GOPROXY=https://goproxy.io,direct \ CGO_ENABLED='1' RUN apk add --no-cache --update \ build-base \ zlib \ zlib-dev # 设置工作目录 WORKDIR /app EXPOSE 7379

使用

可以将对应的开发rocksdb目录挂载进入docker中,使用vscode远程连接进入docker中开发(桥接主机网络)。

bash
代码解读
复制代码
构建镜像 docker build -t grdb:st -f ./Dockerfile . 运行 docker run --name grdb-st -v /tmp/app:/app grdb:st /bin/sh 远程连接并开发

验证环境

验证环境是否安装完成,可以使用rocksdb项目中的make验证,但是,使用golang开发的情况,还需要验证golang的CGO是否能够成功调用。

  • 首先进入容器,创建一个golang项目。

  • 安装grocksdb ,版本确定为1.7.16

    go get github.com/linxGnu/[email protected]

  • 使用以下代码:

    go
    代码解读
    复制代码
    package main import ( "log" "github.com/linxGnu/grocksdb" ) func main() { opts := grocksdb.NewDefaultOptions() opts.SetCreateIfMissing(true) db, err := grocksdb.OpenDb(opts, "./path/to/db") if err != nil { log.Fatalf("Error opening db: %v", err) } defer db.Close() // 进行数据库操作... // 写入数据 writeOpts := grocksdb.NewDefaultWriteOptions() defer writeOpts.Destroy() err = db.Put(writeOpts, []byte("key1"), []byte("value1")) if err != nil { log.Fatalf("Error putting data: %v", err) } // 读取数据 readOpts := grocksdb.NewDefaultReadOptions() defer readOpts.Destroy() value, err := db.Get(readOpts, []byte("key1")) if err != nil { log.Fatalf("Error getting data: %v", err) } defer value.Free() log.Printf("Value: %s", value.Data()) // // 批量写入 // batch := grocksdb.NewWriteBatch() // defer batch.Destroy() // batch.Put([]byte("key1"), []byte("value1")) // batch.Put([]byte("key2"), []byte("value2")) // err = db.Write(writeOpts, batch) // if err != nil { // log.Fatalf("Error writing batch: %v", err) // } // // 迭代器使用 // it := db.NewIterator(readOpts) // defer it.Close() // for it.SeekToFirst(); it.Valid(); it.Next() { // key := it.Key() // value := it.Value() // log.Printf("Key: %s, Value: %s\n", string(key.Data()), string(value.Data())) // } }
  • 执行mod tidy
  • 因为环境变量参数都已经设置好了,可以直接编译 go builid ./main
  • 因为环境已经在docker中设置好,可以直接运行 ./main
  • 如果正确输出,则环境正常

报错备忘记录

+

bash
代码解读
复制代码
/go/pkg/mod/github.com/linx!gnu/[email protected]/cache.go:25:12: could not determine kind of name for C.rocksdb_cache_create_hyper_clock /go/pkg/mod/github.com/linx!gnu/[email protected]/cache.go:31:12: could not determine kind of name for C.rocksdb_cache_create_hyper_clock_opts

go程序编译报错,grocksdb版本太高,对应的rocksdb7.10.2没有,需要将grocksdb将为1.7.16.

+

yaml
代码解读
复制代码
$DEBUG_LEVEL is 0 make: -c: No such file or directory make: -c: No such file or directory make: -c: No such file or directory make: -c: No such file or directory make: -c: No such file or directory make: -c: No such file or directory make: -c: No such file or directory Makefile:245: make_config.mk: No such file or directory make: *** No rule to make target 'make_config.mk'. Stop.

rocksdb项目中执行make报错,未知原因,额外安装一个bash可以解决。

+

perl
代码解读
复制代码
Reason: tried: '/System/Volumes/Preboot/Cryptexes/OS@rpath/librocksdb.7.dylib' (no such file), '/usr/local/lib/librocksdb.7.dylib' (no such file), '/usr/lib/librocksdb.7.dylib' (no such file, not in dyld cache)

编译rocksdb报错,使用了动态库,但是没有配置动态库路径参数。

mac: DYLD_LIBRARY_PATH

liunx: LD_LIBRARY_PATH

+

xxx no found.

由于alpine镜像使用的是musl libc而不是gnu libc,/lib64/ 是不存在的。但他们是兼容的.

​mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2​

+

  • make编译到一半,报错:note: 'uint8_t' is defined in header ''; did you forget to '#include '

    是gcc的版本对应不上,可以通过手动添加:sed -i '1i #include ' table/block_based/data_block_hash_index.h && sed -i '1i #include ' util/string_util.h ​修改。

  • make的install失败,因为alpine中-C命令需要改为-c。
    ​sed -i 's/install -C/install -c/g' Makefile​ (Fix 'install -c' flag)

+

运行编译好的go程序时报错:
​Invalid argument: Compression type ZSTD is not linked with the binary​

这个是因为编译的时候丢了zstd依赖,可能是cmake编译的,通过otool(mac上)或者ldd(liunx上)工具查看对应动态库的依赖。

注:本文转载自juejin.cn的洗澡水加冰的文章"https://juejin.cn/post/7424901430371024935"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

103
后端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top