В
первой части я описал как организованы данные на vdev в ZFS. Вторая часть описывает как работает алгоритм выбора собственно места, куда запись будет идти в данный момент.
Здесь я немного усложню задачу — в первой части был описан только один vdev; здесь их у нас будет несколько, поскольку алгоритм должен выбрать и vdev, куда мы будем писать блок данных, и metaslab внутри vdev'a. В продакшн системе может быть несколько десятков vdev, и правильно распределить данные по ним критично — перебалансировать их мы уже не сможем без копирования всех данных. Цель правильного алгоритма — распараллелить данные так, чтобы на каждом девайсе их было примерно одинаковое количество, выровнять неравномерное заполнение, но и не перегрузить один из девайсов (это будет тормозить запись на весь пул).
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
c1t6d0 ONLINE 0 0 0
c1t5d0 ONLINE 0 0 0
Для начала, важное замечание: ZFS рассчитан на то, что все девайсы в пуле имеют одинаковый размер. Иначе, например если добавить 2Тб диск в пул из 1Тб дисков, на 2Тб диске в результате окажется в два раза больше данных, и он начнёт влиять на суммарный IOPs системы — алгоритм аллокатора учитывает процент заполнения, а не количество данных в байтах.
На данный момент в ZFS есть четыре алгоритма аллокатора. Переменная
zfs_metaslab_ops
содержит поинтер на структуру
space_map_ops_t
, в которой есть поинтеры на семь функций, которые использует каждый конкретный алгоритм. Например, в Illumos используется алгоритм
metaslab_df
, и соответствующий стракт с поинтерами на функции выглядит вот так: