LINUX.ORG.RU

fusepy, распределенная фс на redis


0

2

Всем привет.

Доковырял до более-менее работоспособного состояния распределенную ФС на редисе. Штука пока экспериментальная, косяков и прочих недочетов много. В качестве проверки заливал авишку на 2 гига и пару альбомов - работает адекватно. Еще файрфокс запускал - тоже не жаловался. А вот скомпилить ядро не удалось: make после CC, наверное, во время линкования крашится, жалуясь на память.

Все вкучу:

  • нет flush()
  • как следствие, запись без буфера
  • нет lock()
  • по какой-то причине link() вызвать так и не удалось, поэтому жестких ссылок нет
  • таблица файлов в мускуле
  • файлы разбитые на чанки хранятся в редисах
  • запись с пересечением границы в chunk_size дико тормозит, возможно, из-за необходимости чтения (и еще почему-то медленно Queue.put() работает)
  • сам Fuse() работает в одном потоке (чтение/запись многопоточная)
  • буфер чтения пока растет неограниченно, а убивается только во время записи
  • ноды для хранения выбираются автоматически (правда статистика пока не сохраняется, поэтому выбор всегда один и тот же)
  • load_balance на уровне выбора ноды с минимальным read_requests
  • save/load чанков происходит через бэкенд, поэтому вместо редиса можно будет попробовать что-нибудь другое

mysqlfiletable.py занимается сохранением/чтением из мускула

rcluster.py занимается самими данными

Критика кода и все остальное приветствуется. Хотя я сильно сомневаюсь, что это все кому-то надо :D

rdfs2.tar.gz

Ответ на: комментарий от pianolender

это такой мемкеш, только другой. Ну понятно что со своими плюшками.

Jetty ★★★★★
()

нууу, эээ, скачал. комменты на русском непривычны. Можно было в докстрингах комменты писать. А по коду затрудняюсь что-либо сказать. По мелочи, разве только, но это всё не принципиально.

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

Потом не уверен что надо перед запросами создавать отдельный sql-курсор (cursor = self.db.cursor()). Или это нужно чтобы в многопоточной среде ничего плохого не произошло?

В get_file_nodes ты делаешь select * from ... Зачем селект на звёздочку если тебе только одно поле нужно? Сделай select host_id.

Комменты по аргументам функций бы не помешали. Что такое fh? File handle?

В общем, хорошее начало, главное не останавливаться. Остальное с опытом придёт.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Или это нужно чтобы в многопоточной среде ничего плохого не произошло?

Я не уверен, но в rcluster я делал так с этой целью.

Вообще, потоки - это для меня прямо-таки беда какая-то. Я кстати пофиксил баг с нелинковкой, причина его - кривая очередь записи.

Надо полагать, что линкер выделяет сразу память, а потом пишет рванину рандомной длины. К примеру, offset=317, size=37. Это вынуждает нас предварительно читать чанк.

К моменту записи может не оказаться нужного чанка, поэтому лишнее мы заполняем нулями и помещаем чанки в очередь записи. ДО того, как они успели записаться линкер еще пишет в неразмеченную область, которая также заполняется нулями и помещается в очередь. Таким образом запись ломается. Другими словами, нужна блокировка чтения на время записи для текущего file_id. Я попробовал апдейтить буфер чтения сразу, во время записи свежезаписанными данными, но что-то нифига.

Однопоточная запись работает адекватно.

Видать, все же стоит почитать какую-нибудь литературу по параллельному программированию.

division_hell
() автор топика

Дядь, а выложи на гитхаб? Знаешь, я много времени уже думаю, как ещё попрактиковаться в питоне окромя Джанги и вебдева. Я бы с удовольствием следил за твоим проектом. Надо бы почитать про fuse.

jessey
()
Ответ на: комментарий от division_hell

да, преобразования во float при делении тоже режут глаз. Лучше from future import division :).

Это вынуждает нас предварительно читать чанк.

А как иначе сделать частичное обновление? redis-у то не скажешь «частично обнови чанк». Хотя может и скажешь, я его последний раз года три назад щупал.

нужна блокировка чтения на время записи для текущего file_id

Может не совсем понял суть проблемы, но, вообще говоря, при таком использовании распределённых фс и всегда проблемы. Подумай что будет если чанк обновляется с двух хостов. И знаешь что делает, например, ocfs2? Ничего не делает. Тут или программист делает явные блокировки (через какой-нить lockf) или ловит непонятные баги.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Может не совсем понял суть проблемы, но, вообще говоря, при таком использовании распределённых фс и всегда проблемы.

Суть в том, что частичная запись [chunk----[wb]----chunk] вынуждает читать чанк. Записываем мы чанк целиком. Если мы начали писать следующий чанк до того как записался предыдущий, то мы прочитаем старые данные, а новые данные запишем в миксе с устарвешими, которые попадут в буфер записи ПОСЛЕ тех, которые мы писали в первый раз.

Если я ничего не путаю, то это race condition.

А преобразования во float - да, не шибко красиво. Это, наверное, единственное, что мне не нравится в питоне - не пойму, что помешало сделать также как в и си..

2jessey: Выложу, наверное, только чуть позже. Эта фс - часть одного проекта, и может оказаться не слишком корректно выкладывать ее туда, до куда сможет добраться индексатор. Дабы в плагиате на самого себя потом не обвинили.

Изменений пока особо много не планируется, это:

  • допилить статистику
  • сделать правильную обработку sync-state на случай выпадения тачек из кластера во время чтения/записи. Т.е. если мы во время записи что-то не сможем обновить, то тупо ставим флаг sync=false и периодически пытаемся скопировать чанки с живой ноды на те у которых sync=false.
  • read-fail - просто цикл в read_worker обернуть в try и читать пока не кончатся ноды, в случае чего швырнуть ексепшн

Я думаю, правильно было бы запилить полную многопоточность, но в этом вопросе я не гуру. К примеру, если ядро будет дергать fuse асинхронно во время записи, то может получиться так, что второй блок будет писаться раньше первого, а это проблема. Но и упорядочивать по offset тоже нельзя - мы же не можем сказать, что это не так было задумано.

А как иначе сделать частичное обновление? redis-у то не скажешь «частично обнови чанк». Хотя может и скажешь, я его последний раз года три назад щупал.

Есть операции с range, но они вроде как только для обычных ключей. А у меня чанки хранятся в хешах.

division_hell
() автор топика
Ответ на: комментарий от division_hell

-------

Кстати, вопрос к тем, кто хостит сайты. Если клиенту выдается обычный виртуалхост, и клиент просит redis, то как клиенту дают к нему доступ? К примеру, свою бд с, к примеру, id=uid? Или как обезопасить кэш другого клиента?

division_hell
() автор топика
Ответ на: комментарий от division_hell

Если клиенту выдается обычный виртуалхост

забудь об этом, виртуальных хостинг уже давно неактуален. А так redis может слушать на unix сокет который можно положить к юзеру в папочку.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

А так redis может слушать на unix сокет который можно положить к юзеру в папочку.

Т.е. 1 клиент = 1 инстанс редиса?

division_hell
() автор топика

Критика кода и все остальное приветствуется. Хотя я сильно сомневаюсь, что это все кому-то надо :D

стукнись в почту: real666maverick(собака)gmail.com - есть тема для общения

real_maverick ★★★
()

таблица файлов в мускуле

Или данные в мускуль, или таблицу в редис.

const86 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.