任何 HTTP 客户端都能用——下面用 curl。Rust 开发者可用官方 SDK。也可以把你现有的 Redis / Postgres / Kafka 客户端直接指向 BteloDB。
一行自托管——数据落在 ~/.btelo-db;生产环境设 BTELO_S3_* 用你自己的 S3 桶。
想要零运维?登录后在云端控制台直接创建数据库即可。
docker run -p 4382:4382 ghcr.io/btelolabs/btelo-db-release
每个请求带一个 bearer token。本地可用形如 tnt_<tenant>_<tier> 的 dev token 开箱即用。云端则在控制台创建 API Key。
export BTELO=http://localhost:4382 export TOKEN=tnt_demo_pro
首次写入自动建表。返回 200 即数据已 fsync 落 WAL(kill -9 不丢);偏移严格单调、写完即可读。
# create explicitly (optional)
curl -X PUT $BTELO/v1/tables/events -H "Authorization: Bearer $TOKEN" -d '{}'
# append a document — Idempotency-Key gives you free exactly-once
curl -X POST $BTELO/v1/tables/events/docs \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: $(uuidgen)" \
-d '{"user":"ada","level":"info","msg":"hello"}'对表跑标准 SELECT——聚合、JSON 路径(data['a']['b'])、全文检索(contains/token_match)、向量检索(vector_distance)。
curl -X POST $BTELO/v1/query -H "Authorization: Bearer $TOKEN" \
-d '{"sql":"SELECT level, COUNT(*) AS n FROM events GROUP BY level"}'表之外还有一个线性一致的单键存储:CAS 读写、原子自增、TTL——还能经 _kv 视图用 SQL 查询。
curl -X PUT $BTELO/v1/kv/app/cfg -H "Authorization: Bearer $TOKEN" -d '{"value":{"theme":"dark"}}'
curl $BTELO/v1/kv/app/cfg -H "Authorization: Bearer $TOKEN"
curl -X POST $BTELO/v1/kv/app/hits/increment -H "Authorization: Bearer $TOKEN" -d '{"delta":1}'把表当事件流来 tail。断线用 Last-Event-ID 续传,无重无漏。
curl -N "$BTELO/v1/tables/events/tail?from_offset=latest" -H "Authorization: Bearer $TOKEN"
官方客户端把上面这些都封装好:自动重试、免费幂等键、自动翻页、SSE 续传。
cargo add btelo-db-client tokio serde_json
use btelo_db_client::BteloClient;
#[tokio::main]
async fn main() -> Result<(), btelo_db_client::BteloError> {
let db = BteloClient::new("http://localhost:4382", "tnt_demo_pro");
db.create_table("events", None).await?;
db.append("events", &serde_json::json!({ "user": "ada", "msg": "hello" })).await?;
let res = db.query("SELECT COUNT(*) AS n FROM events", &[]).await?;
println!("{:?}", res.rows);
Ok(())
}BteloDB 同时讲 Postgres、Redis、Kafka 三套线协议——任何语言成熟的、自带连接池的原生驱动都能直接连,无需安装 BteloDB SDK。挑一套合适的协议,把客户端指向对应端口即可(自托管记得发布端口)。密码 / AUTH = 你的 API token。
redis-cli -p 4380 -a tnt_demo_pro # Redis wire · KV / INCR / TTL psql postgres://btelo:tnt_demo_pro@localhost:4383/btelo # Postgres wire · SQL # Kafka clients: bootstrap localhost:4384 · SASL/PLAIN (topic = table)
SELECT 与 INSERT 直接映射到查询与追加;UPDATE/DELETE 映射到异步批量 mutation。psql、JDBC、pgx、node-postgres、psycopg、sqlx——任何讲 pgwire 的都行。
# Postgres wire · port 4383 · password = your API token
psql "postgres://btelo:tnt_demo_pro@localhost:4383/btelo"
# Python · psycopg
cx = psycopg.connect("postgres://btelo:tnt_demo_pro@localhost:4383/btelo")
cx.execute("INSERT INTO events (msg) VALUES (%s)", ["hello"])
print(cx.execute("SELECT count(*) FROM events").fetchone())
# Node · pg
const cx = new Client("postgres://btelo:tnt_demo_pro@localhost:4383/btelo");
await cx.connect();
console.log((await cx.query("SELECT count(*) FROM events")).rows);
# Go · pgx
conn, _ := pgx.Connect(ctx, "postgres://btelo:tnt_demo_pro@localhost:4383/btelo")
# Java · JDBC
DriverManager.getConnection("jdbc:postgresql://localhost:4383/btelo", "btelo", "tnt_demo_pro");RESP2:GET/SET/DEL/EXISTS/MGET、原子 INCR、SCAN、TTL——背后是同一个线性一致 KV(也能经 _kv 视图用 SQL 查)。redis-py、ioredis、go-redis、jedis 或 redis-cli 都行。
# Redis wire · port 4380 · AUTH = your API token
redis-cli -p 4380 -a tnt_demo_pro
# > SET app:greeting "hello" | INCR app:hits | EXPIRE app:greeting 60
# Python · redis-py
r = redis.Redis(port=4380, password="tnt_demo_pro")
r.set("app:greeting", "hello"); print(r.incr("app:hits"))
# Node · ioredis
const r = new Redis({ port: 4380, password: "tnt_demo_pro" });
await r.set("app:greeting", "hello"); await r.incr("app:hits");
# Go · go-redis
rdb := redis.NewClient(&redis.Options{Addr: "localhost:4380", Password: "tnt_demo_pro"})
rdb.Set(ctx, "app:greeting", "hello", 0)SASL/PLAIN 认证;topic = 表。Produce 映射到追加、Fetch 映射到拉取——这里生产的事件随即能用 SQL 查。confluent-kafka、Java 客户端、franz-go 或 rdkafka 都行。
# Kafka wire · port 4384 · SASL/PLAIN, password = your API token (topic = table)
bootstrap.servers=localhost:4384
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.username=btelo
sasl.password=tnt_demo_pro
# Python · confluent-kafka
p = Producer({"bootstrap.servers": "localhost:4384",
"security.protocol": "SASL_PLAINTEXT", "sasl.mechanism": "PLAIN",
"sasl.username": "btelo", "sasl.password": "tnt_demo_pro"})
p.produce("events", value=b'{"msg":"hello"}'); p.flush()
# Java · kafka-clients
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule \
required username="btelo" password="tnt_demo_pro";完整 API 参考 · 浏览组件库 · Docker 镜像与 README · 进入控制台