把git当作一个小型最终一致性的 json 数据库
这几天写了一些有趣的代码:
规格设计
把git当作 json 数据库。做法是这样的:
- 创建一个git仓库
- 为每个最小粒度的数据创建一个独立的json文件({table}.json)
- 客户端通过 Python写git操作代码,实现几个数据库操作接口。
数据库操作接口最小集:
- 初始化:把git仓库拉下来(这个后面可以优化为只拉取指定json文件) git init, git fetch, git checkout branch
- 连接:要更新的时候,同步下最新,git checkout . + git clean -df . + git pull
- 查询:直接读取仓库内的json文件, json.load(f)
- 更新:比对并写入仓库内json文件, json.dump(table,f,indent=4)
- 提交:推送, git add {table}.json, git commit -m f"update {table}", git push
对于 table 的设计:
- 拆分足够小的粒度,使得不同table之间相对独立,避免冲突,这种隔离使得,git push可以自动合并本地和远程仓库的不同(不同文件之间无冲突可自动合并)。
- 同table在更新机制上只要满足最终一致性即可,因此即使同文件发生并发导致某次push失败,也会被后续的更新解决。
- 对于性能要求不高,只要最终一致性满足即可
使用这样的方式好处是:
- 使用一个 git 仓库就可以做分布式有状态功能
- 获得 json table 的版本化支持,通过git的日志可以非常清晰地看到不同table的版本更新,方便比对
- 无需引入独立的数据库
GPT编写的代码
我们把需求提给GPT,得到初版代码:
import os
import json
from git import Repo, exc
class GitJsonDatabase:
def __init__(self, repo_path, remote_url=None, branch='master'):
self.repo_path = repo_path
self.remote_url = remote_url
self.branch = branch
self.repo = None
def init_repo(self):
"""
初始化 Git 仓库,如果远程 URL 存在,则从该远程地址克隆仓库。
否则,在本地创建一个新的仓库。
"""
if self.remote_url:
self.repo = Repo.clone_from(self.remote_url, self.repo_path)
else:
self.repo = Repo.init(self.repo_path)
# Checkout the desired branch
try:
self.repo.git.checkout(self.branch)
except exc.GitCommandError:
# If branch doesn't exist, create it.
self.repo.git.checkout('-b', self.branch)
def connect(self):
"""
连接到仓库,并更新最新版本。
"""
if self.repo is None:
raise Exception("Repository not initialized.")
# Reset local changes and clean up untracked files
self.repo.git.checkout('--', '.')
self.repo.git.clean('-df')
# Pull latest changes from the remote
origin = self.repo.remotes.origin
origin.pull(self.branch)
def query(self, table):
"""
查询指定的 JSON 文件。
"""
file_path = os.path.join(self.repo_path, f"{table}.json")
if not os.path.exists(file_path):
return None
with open(file_path, 'r') as f:
return json.load(f)
def update(self, table, data):
"""
更新指定的 JSON 文件。
"""
file_path = os.path.join(self.repo_path, f"{table}.json")
with open(file_path, 'w') as f:
json.dump(data, f, indent=4)
def commit(self, table, message=None):
"""
提交更改并推送到远端。
"""
if self.repo is None:
raise Exception("Repository not initialized.")
file_path = f"{table}.json"
message = message or f"Update {table}"
# Stage the file and commit
self.repo.git.add(file_path)
self.repo.index.commit(message)
# Push to the remote
origin = self.repo.remotes.origin
origin.push(self.branch)
# 使用示例
# 创建 GitJsonDatabase 实例时需指定本地仓库路径和远程仓库 URL
db = GitJsonDatabase('/path/to/repo', 'https://github.com/user/repo.git')
# 初始化仓库(克隆或创建)
db.init_repo()
# 连接到仓库,同步最新内容
db.connect()
# 查询数据
data = db.query('my_table')
# 更新数据
data['new_key'] = 'new_value'
db.update('my_table', data)
# 提交并推送更改
db.commit('my_table', 'Added new_key to my_table')
--end--
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix