我想构建一个基于 GlusterFS 的分布式存储,具有自动文件复制(AFR)功能,以容错的方式存储用户文件。
但我还想从多个客户端访问存储在 GlusterFS 卷上的 SQLite3 数据库(因此在多台服务器上复制)。这可能吗?多个客户端之间的并发性是否可以得到很好的处理并且不会导致损坏?
或者有没有比 GlusterFS 更好的替代方案来分发 SQLite3 数据库?
答案1
GlusterFS 即使在复制模式下也支持完整的 POSIX 文件/记录级别锁定。它应该可以正常工作。
答案2
我写了一个sqlite_shared_fs_check.sh脚本模拟对 sqlite3 数据库的多次读写。它应该在多台客户端计算机上的同一个 GlusterFS 目录中运行。
我测试了以下配置:
- GlusterFS 3.2 和 sqlite3 3.5.9 (ubuntu 8.10)。数据库没有损坏。
- GlusterFS 3.2 和 sqlite3 3.6.22-1(ubuntu 10.04)。有待确定。
- Ext3 和 sqlite3 3.5.9 (ubuntu 8.10): 测试同时在两个终端窗口运行。测试顺利完成。
上次测试(ext3+sqlite3)的结果将 POSIX 锁定不一致的责任归咎于 GlusterFS 3.2。
这是我用来进行测试的脚本:
#!/bin/bash
function ErrorExit()
{
echo Error: $@
exit 1
}
# Microseconds
timeout=5000
if [ ! -f test.sqlite3 ];
then
touch test.sqlite3
echo 'create table test1 (id integer primary key autoincrement,datetime text,hostname text);' | sqlite3 test.sqlite3 || ErrorExit "Create"
fi
if [ ! -f /tmp/insert.sql ];
then
echo .timeout $timeout > /tmp/insert.sql
echo "insert into test1 values (NULL,datetime('now','localtime'),'$HOSTNAME');" >> /tmp/insert.sql
fi
if [ ! -f select.sql ];
then
echo .timeout $timeout > select.sql
echo "select * from test1 order by id desc limit 1;" >> select.sql
fi
if [ ! -f count.sql ];
then
echo .timeout $timeout > count.sql
echo "select count(*) from test1;" >> count.sql
fi
i=1
while [ $i -le 1000 ];
do
lockfile-create --retry 20 test.sqlite3 || echo -n "?"
sqlite3 test.sqlite3 < /tmp/insert.sql
lockfile-remove test.sqlite3
# Sleep a bit to allow other users
sleep 0.5
lockfile-create --retry 20 test.sqlite3 || echo -n "?"
sqlite3 test.sqlite3 < select.sql >/dev/null || ErrorExit select [$i]
sqlite3 test.sqlite3 < count.sql >/dev/null || ErrorExit count [$i]
lockfile-remove test.sqlite3
let i++
echo -n "."
done
请注意,我必须使用 lockfile-create 实用程序来获取数据库上的锁定,因为 sqlite 的内部锁定不够可靠。
答案3
我认为锁定可能是其中最难的部分。想象一下,写入过程在写入时必须锁定 sqlite3 数据库(文件)。问题是您需要什么级别的并发性?我认为您将面临写入绑定应用程序可能带来的性能问题。
答案4
您会遇到锁定问题,实际上每次只有一个客户端可以写入文件。