Назад | Перейти на главную страницу

Можно ли использовать SQLite с GlusterFS?

Я хочу создать распределенное хранилище на базе GlusterFS с автоматической репликацией файлов (AFR) для отказоустойчивого хранения файлов пользователей.

Но я также хочу получить доступ к базе данных SQLite3, хранящейся на томе GlusterFS (и, следовательно, реплицированной на нескольких серверах) от нескольких клиентов. Является ли это возможным? Будет ли согласованность между несколькими клиентами правильно обработана и не приведет ли к коррупции?

Или есть лучшая альтернатива GlusterFS для распространения базы данных SQLite3?

Я написал 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). TBD.
  • 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 недостаточно надежна.

GlusterFS поддерживает полную блокировку уровня файлов / записей POSIX даже в режиме репликации. Должно работать нормально.

Я думаю, что блокировка может быть самой сложной частью этого. Представьте, что процесс записи должен блокировать базу данных (файл) sqlite3 при записи в нее. Вопрос в том, какой уровень параллелизма вам нужен? Я думаю, вы столкнетесь с возможными проблемами производительности с приложением, привязанным к записи.

У вас будут проблемы с блокировкой, когда (фактически) один клиент за раз может записывать в файл.