2010-09-26 6 views
2

Imaginons que vous construisiez un système de stockage de journalisation/d'écriture en avant-enregistrement. Pouvez-vous simplement l'implémenter par (pour chaque transaction) en ajoutant les données (avec write (2)), en ajoutant un marqueur de validation, puis en fsync-ing?Possibilité d'implémenter la journalisation avec un seul fsync par commit?

Le scénario à prendre en compte est de faire un grand nombre d'écritures dans ce journal, puis de le fsync, et il y a un échec pendant le fsync. Les pointeurs de blocs directs/indirects de l'inode ne sont-ils vidés qu'après le vidage de tous les blocs de données, ou n'y a-t-il aucune garantie que les blocs sont vidés dans l'ordre? Si ce dernier, puis lors de la récupération, si vous voyez un marqueur de validation à la fin du fichier, vous ne pouvez pas croire que les données entre lui et le marqueur de validation précédent est significatif. Ainsi, vous devez vous appuyer sur un autre mécanisme (impliquant au moins un autre fsync) pour déterminer quelle est l'étendue du fichier journal cohérente (par exemple, écrire/fsynchroniser les données, puis écrire/fsynchroniser le marqueur de validation).

Si cela fait une différence, s'interroger principalement sur ext3/ext4 comme contexte.

Répondre

4

Notez que fsync et fdatasync de linux et mac OS sont incorrects par défaut. Windows est correct par défaut, mais peut émuler linux à des fins d'analyse comparative.

En outre, fdatasync émet plusieurs écritures de disque si vous ajoutez à la fin d'un fichier, car il doit mettre à jour le fichier inode avec la nouvelle longueur. Si vous voulez avoir une écriture par commit, le mieux est de pré-allouer l'espace du journal, de stocker un CRC des entrées du journal dans le marqueur de validation et d'émettre un seul fdatasync() lors de la validation. De cette façon, peu importe la quantité de réorganisation du système d'exploitation/matériel derrière votre dos, vous pouvez trouver un préfixe du journal qui a réellement atteint le disque.

Si vous souhaitez utiliser le journal pour les validations durables ou écrire à l'avance, les choses deviennent plus difficiles, car vous devez vous assurer que fsync fonctionne réellement. Sous Linux, vous devez désactiver le cache d'écriture de disque avec hdparm ou monter la partition avec le paramètre barrier défini sur true. [Edit: Je suis corrigé, la barrière ne semble pas donner la bonne sémantique. SATA et SCSI introduisent un certain nombre de primitives, telles que des barrières d'écriture et des files d'attente de commandes natives, qui permettent aux systèmes d'exploitation d'exporter des primitives permettant la journalisation en écriture anticipée. De ce que je peux dire des pages de manuel et en ligne, Linux les expose uniquement aux développeurs de systèmes de fichiers, pas aux utilisateurs.]

Paradoxalement, la désactivation du cache d'écriture de disque conduit parfois à de meilleures performances, car vous avez plus de contrôle sur la programmation de l'écriture dans l'utilisateur. espace; Si le disque met en file d'attente un tas de demandes d'écriture synchrones, vous finissez par exposer des pics de latence étranges à l'application. La désactivation du cache en écriture empêche que cela se produise.

Enfin, les systèmes réels utilisent la validation de groupe et < 1 écriture synchronisée par validation avec des charges de travail simultanées.

+1

Merci pour la réponse Russell - cela vous dérangerait-il de clarifier ce que vous voulez dire par fsync et fdatasync étant incorrect? Et dans la technique de pré-allocation, comment accomplissez-vous la pré-allocation? – Yang

+0

Question finale sur la relation entre 'hdparm -W' et' barrier = 1': à la lecture des docs, ma compréhension de 'hdparm -W' est qu'il bascule le cache interne du périphérique, alors que' barrier = 1' contrôle si nous rincer les blocs de la couche de bloc à l'appareil.Est-ce que 'barrier = 1' garantit également que les blocs rincés dépassent le cache interne de l'appareil? – Yang

+0

Et il semble que 'barrier = 1' n'affecte que les blocs de journal - n'auriez-vous pas besoin de désactiver la mise en cache d'écriture de toute façon pour des fsyncs durables? – Yang

1

Il n'y a aucune garantie sur l'ordre dans lequel les blocs sont vidés sur le disque. Ces jours-ci même le lecteur lui-même peut réorganiser les blocs sur leur chemin vers les plateaux.

Si vous voulez appliquer la commande, vous devez au moins fdatasync() entre les écritures que vous souhaitez commander. Toutes les promesses de synchronisation est que quand il renvoie, tout écrit avant que la synchronisation a atteint le stockage.

Questions connexes