19 votes

Meilleure compression pour les envois/récupérations ZFS

J'envoie des instantanés ZFS incrémentiels sur une ligne T1 point à point et nous en sommes à un point où l'équivalent d'une journée d'instantanés peut à peine passer le fil avant que la sauvegarde suivante ne commence. Notre commande d'envoi/récupération est la suivante :

zfs send -i tank/vm@2009-10-10 tank/vm@2009-10-12 | bzip2 -c | \
ssh offsite-backup "bzcat | zfs recv -F tank/vm"

J'ai beaucoup de cycles de CPU à épargner. Existe-t-il un meilleur algorithme de compression ou une méthode alternative que je peux utiliser pour faire passer moins de données sur la ligne ?

1 votes

H

0 votes

Y

3 votes

H

16voto

tsbertalan Points 467

Les choses ont changé depuis que cette question a été posée :

1 : ZFS supporte maintenant la réplication compressée, il suffit d'ajouter l'indicateur -c à la commande zfs send, et les blocs qui ont été compressés sur le disque resteront compressés lorsqu'ils passeront dans le tuyau vers l'autre extrémité. Il peut encore y avoir plus de compression à gagner, parce que la compression par défaut dans ZFS est lz4.

2 : Le meilleur compresseur à utiliser dans ce cas est zstd (ZStandard), il a maintenant un mode 'adaptatif' qui changera le niveau de compression (entre les 19+ niveaux supportés, plus les nouveaux niveaux plus rapides zstd-fast) basé sur la vitesse du lien entre zfs send et zfs recv. Il compresse autant qu'il peut tout en gardant la file d'attente des données attendant de sortir du tuyau au minimum. Si votre liaison est rapide, il ne perdra pas de temps à compresser davantage les données, et si votre liaison est lente, il continuera à travailler pour compresser davantage les données et vous fera gagner du temps au final. Il supporte également la compression threadée, ce qui me permet de tirer parti de plusieurs cœurs, ce que gzip et bzip ne font pas, en dehors des versions spéciales comme pigzip.

10voto

aarontomosky Points 101

Voici ce que j'ai appris en faisant exactement la même chose que vous. Je suggère d'utiliser mbuffer. Lorsque j'ai testé dans mon environnement, cela n'a été utile que pour la réception. Sans cela, l'envoi ralentissait tandis que la réception rattrapait son retard.

Quelques exemples : http://everycity.co.uk/alasdair/2010/07/using-mbuffer-to-speed-up-slow-zfs-send-zfs-receive/

Page d'accueil avec options et syntaxe http://www.maier-komor.de/mbuffer.html

La commande d'envoi de ma réplication script :

zfs send -i tank/pool@oldsnap tank/pool@newsnap | ssh -c arcfour remotehostip "mbuffer -s 128k -m 1G | zfs receive -F tank/pool"

Cela fait tourner mbuffer sur l'hôte distant comme tampon de réception pour que l'envoi soit aussi rapide que possible. J'utilise une ligne de 20mbit et j'ai trouvé que le fait d'avoir mbuffer du côté de l'envoi n'aidait pas. De plus, ma boîte zfs principale utilise toute sa mémoire vive comme cache, donc donner même 1g à mbuffer m'obligerait à réduire la taille de certains caches.

De plus, et ce n'est pas vraiment mon domaine d'expertise, je pense qu'il est préférable de laisser ssh faire la compression. Dans votre exemple, je pense que vous utilisez bzip et ensuite ssh qui par défaut utilise la compression, donc SSH essaie de compresser un flux compressé. J'ai fini par utiliser arcfour comme chiffrement car c'est le moins gourmand en ressources CPU et c'était important pour moi. Vous pouvez obtenir de meilleurs résultats avec un autre chiffrement, mais je vous suggère de laisser SSH se charger de la compression (ou de désactiver la compression ssh si vous voulez vraiment utiliser quelque chose qu'il ne prend pas en charge).

Ce qui est vraiment intéressant, c'est que l'utilisation de mbuffer pour l'envoi et la réception sur localhost accélère également les choses :

zfs send tank/pool@snapshot | mbuffer -s 128k -m 4G -o - | zfs receive -F tank2/pool

J'ai trouvé que 4g pour les transferts locaux semble être la meilleure solution pour moi. Cela montre bien que zfs send/receive n'aime pas vraiment la latence ou toute autre pause dans le flux pour fonctionner au mieux.

C'est juste mon expérience, j'espère que cela vous aidera. Il m'a fallu un certain temps pour comprendre tout cela.

1 votes

Merci beaucoup pour cet article. En regardant zfs send de plus près, j'ai rapidement eu l'impression qu'il avait un mauvais comportement (aka "design") lors de l'envoi vers une cible à latence limitée. Après une douzaine de résultats, je me suis dit que zfs ne pouvait en aucun cas être responsable de quoi que ce soit. Je vous suis très reconnaissant d'avoir pris le temps de vous pencher sur la question et d'avoir publié vos résultats.

4voto

soyayix Points 31

J'utilise pbzip2 tout le temps (bzip2 parallèle) lors de l'envoi sur WAN. Comme il est threadé, vous pouvez spécifier le nombre de threads à utiliser avec l'option -p. Installez d'abord pbzip2 sur les hôtes d'envoi et de réception, les instructions d'installation se trouvent à l'adresse suivante http://compression.ca/pbzip2/ .

zfs send -i tank/vm@2009-10-10 tank/vm@2009-10-12 | pbzip2 -c | \
ssh offsite-backup "pbzip2 -dc | zfs recv -F tank/vm"

La clé principale est de créer des instantanés à intervalles fréquents (~10mins) pour réduire la taille de l'instantané puis d'envoyer chaque instantané. ssh ne reprendra pas à partir d'un flux d'instantanés interrompu, donc si vous avez un énorme instantané à envoyer, envoyez le flux vers pbzip2 puis divisez-le en morceaux de taille gérable, puis rsync les fichiers divisés vers l'hôte récepteur, puis envoyez vers zfs recv les fichiers pbzip2 concaténés.

zfs send -i tank/vm@2009-10-10 tank/vm@2009-10-12 | pbzip2 -c | \
split -b 500M - /somedir/snap-inc-10-to-12.pbzip2--

cela produira des fichiers nommés en morceaux de 500MB :

/somedir/snap-inc-10-to-12.pbzip2--aa
/somedir/snap-inc-10-to-12.pbzip2--ab
/somedir/snap-inc-10-to-12.pbzip2--ac
...

rsync vers l'hôte récepteur plusieurs fois (vous pouvez rsync avant même que zfs send ne se termine ou dès que vous voyez un morceau complet de 500MB), appuyez sur ctrl+c à tout moment pour annuler :

while [[ true ]]; do rsync -avP /somedir/snap-inc-10-to-12.pbzip2--* offsite-backup:/somedir ; sleep 1; done;

zfs recevoir :

cat /somedir/snap-inc-10-to-12.pbzip2--* | pbzip2 -dc | zfs recv -Fv tank/vm

Un ami de l'utilisateur est mentionné : Pour ce que ça vaut. Je ne ferais pas un envoi direct | compresser | décompresser | recevoir cela peut conduire à des problèmes à l'extrémité de réception si la ligne de transfert se casse et vos pools seront hors ligne pendant un long moment pendant la réception. - J'ai déjà rencontré des problèmes avec des versions zfs plus anciennes <28 dans l'hôte récepteur si un envoi/réception en cours est interrompu par des chutes de réseau, mais pas au point que les pools soient hors ligne. C'est intéressant. Renvoyez l'instantané uniquement si le "zfs recv" a quitté l'extrémité de réception. Arrêtez le "zfs recv" manuellement si nécessaire. zfs send/recv est bien meilleur maintenant sous FreeBSD ou Linux.

2voto

Dave Points 864

Il s'agit d'une réponse à votre question spécifique :

Vous pouvez essayer rzip mais son fonctionnement est un peu différent de celui de compress/bzip/gzip :

rzip s'attend à pouvoir lire l'ensemble du fichier, il ne peut donc pas être exécuté dans un pipeline. Cela augmentera considérablement vos besoins en stockage local et vous ne serez pas en mesure d'exécuter une sauvegarde et d'envoyer la sauvegarde sur le fil en un seul tuyau. Ceci étant dit, les fichiers résultants, du moins d'après este sont un peu plus petits.

Si votre contrainte de ressources est votre tuyau, vous devrez de toute façon effectuer des sauvegardes 24 heures sur 24, 7 jours sur 7, et vous devrez donc copier des instantanés en permanence en espérant pouvoir tenir le coup.

Votre nouveau commandement serait :

remotedir=/big/filesystem/on/remote/machine/
while 
  snaploc=/some/big/filesystem/
  now=$(date +%s)
  snap=snapshot.$now.zfssnap
  test -f $snaploc/$snap
do
  sleep 1
done

zfs send -i tank/vm@2009-10-10 tank/vm@2009-10-12 > $snaploc/$snap &&
rzip $snaploc/$snap &&
ssh offsite-backup "
        cat > $remotedir/$snap.rzip && 
        rzip -d $remotedir/$snap.rzip && 
        zfs recv -F tank/vm < $remotedir/$snap &&
        rm $remotedir/$snap " < $snaploc/$snap &&
rm $snaploc/$snap

Vous devrez mettre en place une meilleure correction des erreurs et envisager d'utiliser quelque chose comme rsync pour transférer les fichiers compressés. Ainsi, si le transfert échoue en cours de route, vous pourrez reprendre là où vous en étiez.

2voto

semi Points 726

On dirait que vous avez essayé tous les meilleurs mécanismes de compression et que vous êtes toujours limité par la vitesse de la ligne. En supposant que l'utilisation d'une ligne plus rapide est hors de question, avez-vous envisagé d'exécuter les sauvegardes moins fréquemment afin qu'elles aient plus de temps pour s'exécuter ?

Sinon, existe-t-il un moyen de réduire la quantité de données écrites ? Sans connaître votre pile d'applications, il est difficile de dire comment, mais faire des choses comme s'assurer que les applications écrasent les fichiers existants au lieu d'en créer de nouveaux pourrait aider. Et assurez-vous que vous n'enregistrez pas de sauvegardes de fichiers temporaires/cache dont vous n'avez pas besoin.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X