OceanBase TableAPI实践案例(Rust)

2024年 5月 7日 71.6k 0

引子

这是OceanBase TableAPI实践案例(Java)的姊妹篇,上一篇比较全面的比较全面的介绍了TableAPI的相关概念,以及基本的环境搭建,因此这篇不再赘述。本文将主要介绍TableAPI的Rust客户端obkv-table-client-rs ,因为这个开源项目相关说明较少,初学者可能未必能够直接上手操作,所以可以将本文内容作为该项目的增强版README。

想更好的理解本文内容需要有Rust语言基础、OceanBase基础、了解TableAPI工作原理。

注:为了不增加冗余篇幅,请提前阅读TableAPI官方文档OceanBase TableAPI实践案例(Java)两篇文章。

环境准备

假设按照OceanBase TableAPI实践案例(Java)中的方法,搭建好了OceanBase数据库环境、ob-configserver环境。

Rust环境搭建

  • 安装
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  • 版本
rustc rustc 1.59.0-nightly (f1ce0e6a0 2022-01-05)
rustup rustup 1.25.1 (bb60b1e89 2022-07-12)
cargo cargo 1.59.0-nightly (358e79fe5 2022-01-04)

obkv-table-client-rs工程(可选)

该步骤为可选,这一章节主要介绍如何编译obkv-table-client-rs工程。

  • 获取工程源码
git clone https://github.com/oceanbase/obkv-table-client-rs.git
  • 配置cargo国内镜像(可选),主要是为了加快下载速度,节省时间
vim ~/.cargo/config
# 写入以下内容
[source.crates-io] 
registry = "https://github.com/rust-lang/crates.io-index" 
replace-with = 'tuna' 
[source.ustc] 
registry = "git://mirrors.ustc.edu.cn/crates.io-index"
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"
  • 编译工程
cd obkv-table-client-rs
cargo build

Rust客户端测试

  • 新建工程
# 在obkv-table-client-rs同级目录下
cargo new obkv_cli

OceanBase TableAPI实践案例(Rust)-1

  • 测试代码
// Copyright 2022 CeresDB Project Authors. Licensed under Apache-2.0.

extern crate obkv;

use std::{sync::Arc, thread, time};

use obkv::{serde_obkv::value::Value, Builder, ClientConfig, ObTableClient, RunningMode, Table};

// TODO: use test conf to control which environments to test.
const TEST_FULL_USER_NAME: &str = "frank@sys#obcluster";
const TEST_URL: &str = "http://172.18.108.43:8080/services?Action=ObRootServiceInfo&ObCluster=obcluster&database=test";
const TEST_PASSWORD: &str = "frank";
const TEST_SYS_USER_NAME: &str = "root@sys";
const TEST_SYS_PASSWORD: &str = "root";

fn build_client(mode: RunningMode) -> ObTableClient {
    let mut config = ClientConfig::default();
    config.min_idle_conns_per_server = 1;
    config.max_conns_per_server = 1;
    config.rpc_connect_timeout = std::time::Duration::from_secs(1);
    config.metadata_mysql_conn_pool_max_size = 1;
    config.metadata_mysql_conn_pool_min_size = 1;

    let builder = Builder::new()
        .full_user_name(TEST_FULL_USER_NAME)
        .param_url(TEST_URL)
        .running_mode(mode)
        .password(TEST_PASSWORD)
        .sys_user_name(TEST_SYS_USER_NAME)
        .sys_password(TEST_SYS_PASSWORD);

    let client = builder.build();

    assert!(client.is_ok());

    let client = client.unwrap();
    client.init().expect("Fail to create obkv client.");
    client
}

const TABLE_NAME: &str = "series_key_to_id_0";
// read and write the table:
// create table series_key_to_id_0 (
//  series_key VARBINARY(8096) NOT NULL,
//  series_id BIGINT NOT NULL,
//  PRIMARY KEY(series_key),
//  KEY index_id(series_id)
// );
fn concurrent_insert(client: Arc<ObTableClient>) {
    let mut thds = Vec::with_capacity(20);
    for i in 0..50 {
        let client = client.clone();
        let thd = thread::spawn(move || {
            for j in i * 100..(i * 100 + 50) {
                let series_key = format!("series_key_test_padding_padding_{}", j);
                let series_id = j * j;
                client
                    .insert(
                        TABLE_NAME,
                        vec![Value::from(series_key.clone())],
                        vec!["series_id".to_owned()],
                        vec![Value::from(series_id as i64)],
                    )
                    .expect(&format!("fail to insert row:{} {}", series_key, series_id));
            }
        });
        thds.push(thd);
    }

    for (i, thd) in thds.into_iter().enumerate() {
        thd.join().expect(&format!("thread#{} fail to join", i));
    }
}

fn main() {
    let client = build_client(RunningMode::Normal);
    client
        .truncate_table(TABLE_NAME)
        .expect("fail to truncate the table");
    let start = time::Instant::now();
    concurrent_insert(Arc::new(client));
    let elapsed = time::Instant::now() - start;
    println!("Benches::concurrent_insert cost time:{:?}", elapsed);
}

根据你自己的情况修改以下几个参数/变量:

const TEST_FULL_USER_NAME: &str = "frank@sys#obcluster";
const TEST_URL: &str = "http://172.18.108.43:8080/services?Action=ObRootServiceInfo&ObCluster=obcluster&database=test";
const TEST_PASSWORD: &str = "frank";
const TEST_SYS_USER_NAME: &str = "root@sys";
const TEST_SYS_PASSWORD: &str = "root";
  • Cargo.toml
[package]
name = "obkv_cli"
version = "0.1.0"
edition = "2022"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
obkv-table-client-rs = { path = "../obkv-table-client-rs" }
  • 编译
cd obkv_cli
cargo build
  • 运行
cargo run

Q&A

  • 运行报错
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.21s
     Running `target/debug/obkv_cli`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: MySqlError { ERROR 1193 (HY000): Unknown system variable 'socket' }', /home/frank/.cargo/registry/src/mirrors.tuna.tsinghua.edu.cn-df7c3c540f42cdbd/mysql-16.1.0/src/conn/mod.rs:1760:61
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

问题跟踪:https://github.com/oceanbase/obkv-table-client-rs/issues/6

总结

相对与obkv-table-client-java 客户端,obkv-table-client-rs 运行时会有一些问题,可能是版本相关的问题,应该可以很快解决。

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论