Про zfs primarycache

У одного моего друга есть FreeBSD бокс, на нем ZFS, Samba и 10G-ethernet. К этому боксу подключена рабочая станция с Acronis Workstation, которая туда делает бэкапы.

Бэкапы делаются на отдельный zfs pool, я подумал "а нахрена бэкапами размывать кэши" и сказал этому пулу

zfs set primarycache=metadata zbackup

Получилась такая фигня: если у Acronis-а запустить проверку бэкапа, то:

1. C ZFS-тома читается ~150-200 мегабайт/сек:
$ zpool iostat zbackup 1
...
zbackup     2,36T  2,17T    195      0   195M      0
zbackup     2,36T  2,17T    157    152   157M  6,62M
zbackup     2,36T  2,17T    205      0   206M      0
zbackup     2,36T  2,17T    201      0   202M      0

По iostat -x примерно та же картина, суммарное чтение по дискам примерно равно тому, что zpool iostat кажет.

2. А в сеть уходит раза в 3-4 меньше:

$ netstat -I ix0 1
            input            ix0           output
   packets  errs idrops      bytes    packets  errs      bytes colls
      3584     0     0     254240       6832     0   59136000     0
      3584     0     0     254240       6831     0   59135942     0
      2410     0     0     172000       4580     0   39600320     0
      2832     0     0     202560       5376     0   46464512     0

Пробовал запретить ZFS prefetch в предположении, что там префетчится не то, что акронис хочет читать. Запретил, перезагрузился, префетча нет, фигня есть.

Вернул обратно:

zfs set primarycache=all zbackup

И все стало как надо:

Без префетча - те же самые under 100Mb/sec, а если вернуть префетч, то совсем хорошо:

zpool:

zbackup     2,36T  2,17T    206      0   205M      0
zbackup     2,36T  2,17T    160      0   159M      0
zbackup     2,36T  2,17T    162      0   161M      0
zbackup     2,36T  2,17T    159      0   157M      0

Интерфейс:

     14167     0     0    1002592      26419     0  234453240     0
      9861     0     0     702772      18131     0  161143124     0
     14081     0     0     997088      26158     0  229747404     0
     11541     0     0     816768      21222     0  184760500     0
     10158     0     0     721152      18910     0  167820930     0
      9270     0     0     657216      17185     0  152605772     0

Мораль: даже если на животе есть гайка, крутить ее - необязательно.

Более-менее понятно что происходило:

  • без префетча - медленно
  • с префетчем и не-сохранением его результатов - медленно и глупо
  • Ну а со стандартными настройками просто хорошо, с поправкой на размытие кэша (эти много гигабайт бэкапа будут жрать и RAM тоже)
  • (из комментариев подниму): если размер записи ZFS меньше больше (зачеркнута исходная ошибка) размера запроса smbd, то куда девается лишнее? Без кэширования данных - вероятно "в никуда"....

Comments

Я бы немного переиначил: если есть гайка - её обязательно покрутят :-). Я где-то полгода назад тоже крутил: windows-samba-zfs (primarycache=metadata и не только). Не могу сказать, что докрутил до полного понимания :-). Но наводящий вопрос задать смогу: а какая по твоему в данной связке основная причина снижения скорости чтения при кэшировании в zfs только метаданных и можно ли её устранить/уменьшить?

Я исходников не читал, не до грибов, поэтому предполагаю
1) prefetch + primarycache=metadata => префетч есть, но его результаты идут в трубу (не сохраняются в ARC). На дисках 200Mb/sec, на сети - 50 (цифры условные)
2) primarycache=metadata, без префетча: 50 на дисках (потому что in advance не читаем), столько же отдается наружу
3) prefetch + primarycahe=all => префетч есть, на дисках 200, результаты префетча не выкидывают, а отдают приложению (когда попросит - а попросит почти сразу), поэтому в сети тоже 200.

Это ж легко проверить :-). Да и сам перед этим написал/проверил: "C ZFS-тома читается ~150-200 мегабайт/сек".

Вопроса про "устранить-уменьшить" не понял.

Если понятна причина ... :-).

Если вам есть что содержательное сказать - так скажите.

Все исходные данные ты уже получил. Я ещё помню, что при выключенном префетче и кэшировании только метаданных дополнительно смотрел на размер считанных данных с zfs по сравнению с запрашиваемыми.
У меня получалось следующее: windows по умолчанию читал по smb блоками по 64k, с zfs происходило считывание recordsize (думаю у тебя 1M) и при выключенном кэшировании данных выбирались только нужные 64k, а при следующем smb запросе опять читалась recordsize (причём одна и таже читалась recordsize/64k). Вывод: если уравнять размеры smb запроса и recordsize, то скорость считывания повысится. У меня на 1 гигабите скорости считывания становились почти равными.

Ага, так понятнее.
В-общем, наверное проще вернуть полное кэширование.

Ну либо recordsize датасету с бекапами привести в соотвествие.

У меня там, по счастью, 4+1 диск, то есть да, можно и даже без потерь места.

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

да, мануал говорит что recordsize только для новых

Да и нормально, можно попробовать (на свежих бэкапов), а потом быстро откатить если не.

Не будет сильным оффтопиком если я на zfsonlinux пожалуюсь?

У меня тут страшная конструкция -- zpool поверх lvm тома, который поверх md0 (такое легаси, с которым жить месяц или два). Так вот, в процессе rsync'а тома с всяким хламом типа гитов, архивов книжек итд процессики стали весело подвисать минуты на две -- и rsync, и все кто хотели писать в /home который уже на zfs был к тому моменту. Полечилось вроде от logbias=throughput (окончательно проверю сегодня, допереносив остальные тома)

Собственно -- вопрос, может ли дело быть в "подлежащем" lvm+md (raid 1), в кривом ssd который кеш (или в том что я явно туда zil не унес), или это zfsonlinux немного странный? lvm/md будет выкинуть как только

Ну и спрошу напоследок -- стоит ли явно сделать `log sdc1 cache sdc2` или `cache sdc` ему вполне достаточно.

люди raid-контроллеры в dumb-режим прошивают, а вы про такой бутерброд спрашиваете.
Ну что тут можно ответить. хрен его знает....

log - если есть синхронная запись, то не помешает. Нет - будет пустой стоять.

ага, с logbias стало понятно

А бутерброд -- таки издержки миграции.
Надо унести (или пересоздать) на zfs рут, и тогда буду выдергивать бутерброд (поставлю md1 в degrade и отдам диск целиком пулу как миррор, потом после ресилвера повторю)

От бутерброда я избавился, все по плану.
Единственное было мелкое неудобство -- у grub-x86_64.efi где то внутри референс на дефолтный раздел с его "кишками" и конфигами (и там был старый том на lvm). Пришлось сплясать и собрать ему grub rescue на ноутбуке.

Видимо efi не позволяет такое держать прямо на efi разделе (или позволяет, но требует какого-то нестандартного подхода -- стандарт: либо все на efi включая ядра и initrd, либо все на руте, а в efi только образ груба). Мне же хочется неизменную часть (груб с кишками и большей частью конфига) держать на efi, а список ядер и сами ядра/initrd держать на руте (в /nix/store) и никуда не копировать, чтобы GC было легче их убирать когда они не нужны.

А про софт-локапы я писал в рассылку, там говорят не пользуйся консумерскими sata, они в принципе не умеют нормально в рейде жить. И что скорее всего один из пары наедается потихоньку. С log sdc1 cache sdc2 (8 и 56г соотвественно) оно как-то нивелировалось до терпимого, но все равно буду менять диски при первой же возможности.
Подробности тут -- может еще что напишут, сейчас выходные таки (подвесил ссылку на тред в архиве -- вдруг кому полезно будет)

"(из комментариев подниму): если размер записи ZFS меньше размера запроса smbd, то куда девается лишнее? Без кэширования данных - вероятно "в никуда"...."

Что-то не могу сообразить к чему это? Пусть размер smb запроса чтения 64k и recordsize=32k. Для выполнения запроса прочитаются две recordsize. Причём здесь "Без кэширования данных - вероятно "в никуда"....""? Скажу больше, при такой конфигурации на слабой машине (при кэшировании только метаданных) получалось более быстрое чтение, чем при recordsize=64k. "Конвеер" zfs работал более плавно и задержки уменьшались.

Конечно, больше (а не меньше)
Вечером обновлял, горшок уже не варил, встал вчера очень рано.