FoundationDB 分布式数据库

FreeGuideOnline 最新 2026-07-12

bash wget https://github.com/apple/foundationdb/releases/download/7.3.3/foundationdb-clients_7.3.3-1_amd64.deb wget https://github.com/apple/foundationdb/releases/download/7.3.3/foundationdb-server_7.3.3-1_amd64.deb sudo dpkg -i foundationdb-clients_7.3.3-1_amd64.deb foundationdb-server_7.3.3-1_amd64.deb


macOS 可使用官方 `.pkg` 安装包。

### 2. 启动服务与配置

启动 FoundationDB 服务并初始化数据库:

```bash
sudo service foundationdb start                 # Linux
# 或 launchctl load /Library/LaunchDaemons/com.foundationdb.fdbmonitor.plist  # macOS

# 配置单机内存模式(方便测试)
sudo fdbcli --exec "configure new single memory"

命令解释:

  • single 表示单副本,memory 表示数据仅存内存(测试用,重启丢失)。生产环境应使用 doubletriple 存储为磁盘。
  • 可随时通过 fdbcli 管理集群。

3. 验证集群状态

fdbcli

进入交互界面后执行 status,应看到类似输出:

Cluster:
  FoundationDB processes - 1
  ...
  Redundancy mode - single
  Storage engine - memory-2

表明单节点集群已就绪。

编程入门:Python 示例

FoundationDB 提供多语言 API,这里以 Python 为例。安装客户端库:

pip install foundationdb

基本事务操作

import foundationdb

# 配置 API 版本(重要)
foundationdb.api_version(720)

# 打开数据库(默认集群配置)
db = foundationdb.open()

# 写入数据
@foundationdb.transactional
def set_key(tr, key, value):
    tr[key.encode()] = value.encode()

set_key(db, 'hello', 'world')

# 读回数据
@foundationdb.transactional
def get_key(tr, key):
    v = tr[key.encode()]
    return v.decode() if v else None

print(get_key(db, 'hello'))  # 输出 'world'

foundationdb.transactional 装饰器会自动处理事务的重试逻辑。在函数内部,通过 tr 对象执行读写,所有操作在函数结束前不会提交,发生冲突时会自动重试整个函数。

使用目录层

import fdb.directory

dir_layer = fdb.directory.DirectoryLayer()

@foundationdb.transactional
def init_dir(tr):
    return dir_layer.create_or_open(tr, ('my_app', 'users'))

user_dir = init_dir(db)   # 返回 DirectorySubspace 对象

# 在目录下写入
@foundationdb.transactional
def add_user(tr, subspace, user_id, name):
    tr[subspace.pack((user_id,))] = name.encode()

add_user(db, user_dir, 1, 'Alice')

# 范围扫描该目录下所有键
@foundationdb.transactional
def list_users(tr, subspace):
    # subspace.range() 返回该目录下所有键的范围
    for k, v in tr.get_range(subspace.range(), limit=10):
        print(subspace.unpack(k)[0], '->', v.decode())

list_users(db, user_dir)

packunpack 方法将 Python 原生元组编码为字节键,使用目录层的 Tuple 编码对整数、字符串等进行排序友好的编码。

数据模型设计原则

使用 FoundationDB 通常需要将业务模型映射到键值对,并利用有序键设计查询模式。以下是几个关键设计思路:

1. 为查询模式构建索引

FoundationDB 没有内置二级索引,需要自己维护。例如,若要按邮箱查找用户,可以维护一个从 emailuser_id 的索引键:

# 主数据:  user:{user_id} -> {name, email, ...}
# 索引表:  user_by_email:{email} -> user_id

在事务中同时更新主数据和索引,保证一致性。

2. 利用键前缀实现范围扫描

将实体分组存放,通过前缀扫描得到相关对象。例如:

msg:{chat_id}:{ts} -> message_body