miércoles, 9 de noviembre de 2011

PoC: Playing with the ZFS compression



Como muchos sabrán, ZFS o ZettaByte filesystem es un sistema de 128 bits archivos diseñado por los ingenieros de Sun Microsystems para ser realmente grande, Jeff Bonwick, el arquitecto jefe de Sun para ZFS, dijo "Llenar un sistema de archivos de 128 bits excedería los límites cuánticos de almacenamiento de la Tierra. No puedes rellenarlo sin hervir los océanos". Una de las ventajas prácticas de ZFS es que integra el volume manager y el filesystem en un solo toolkit.

En este post, trataré de hacer una prueba de conceptos sobre uno de los features más interesantes que tiene ZFS, que es la compresión. Actualmente vivimos en una época en que el storage es un recurso barato, y el sentido de usar esta es mejorar de manera considerable el I/O del dataset, el dato al estar compreso ocupa menos, por lo cual se tienen que leer y escribir datos mas pequeños en el disco lo cual reduce la taza de I/O pero aumenta gradualmente la carga de las CPU's del equipo.

Para este ejemplo sobre FreeBSD 8.2 64 bits vamos a crear filedisks, iniciando un pool de discos con mdadm.
Vamos manos a la obra:

Como primera medida, vamos a darle soporte a ZFS en el sistema operativo (FreeBSD por default lo deshabilita), para ello tenemos que añadir el parámetro vfs.zfs.prefetch_disable=0 en el /boot/loader.conf y rebootear el equipo.
tokyo # echo "vfs.zfs.prefetch_disable=0" > /boot/loader.conf
tokyo # reboot
Una vez hecho esto, vamos a crear los filedisk propiamente dichos, en este caso lo haremos en /tmp, y seran en total 5 con una capacidad de 200M cada uno (1GB en total de storage), lo que utilizando bloques de 1K, suman un total de 204800 bloques. Para ello utilizaremos dd. Repetimos lo siguiente para cada uno de los discos:
tokyo # dd if=/dev/urandom of=/tmp/disk1 bs=1k count=204800
204800+0 records in
204800+0 records out
209715200 bytes transferred in 4.909060 secs (42720032 bytes/sec)
Una vez listos los cinco filedisks, vamos a crear el pool usando mdadm, el parámetro -a hace un add del device dentro del pool, el parámetro -t indica el tipo de device (vnode: en este caso el filedisk), el parámetro -f indica la localización en el filesystem del vnode, y el parámetro -u el número de device a crear en /dev/.
tokyo # mdconfig -a -t vnode -f /tmp/disk1 -u 1
tokyo # mdconfig -a -t vnode -f /tmp/disk2 -u 2
tokyo # mdconfig -a -t vnode -f /tmp/disk3 -u 3
tokyo # mdconfig -a -t vnode -f /tmp/disk4 -u 4
tokyo # mdconfig -a -t vnode -f /tmp/disk5 -u 5
Esto nos creara las correspondientes entradas de block devices bajo el nombre de /dev/mdX siendo X un número comprendido entre 1 y 5 correspondiente a los devices que inicializamos.

Actualmente ya contamos todos los elementos para comenzar.  Lo primero que debemos hacer una vez que tenemos todo listo es crear un pool de ZFS, en este caso vamos a hacerlo utilizando RAIDZ 2; raidz es un esquema de redundancia integrada especial utilizado por ZFS, que es parecido a RAID 5 utilizando un stripe variable, esto es debido a que lo maneja el propio filesystem. RAIDZ 2 añade un bloque extra de paridad para dar aún mayor redundancia de datos. Creamos nuestro pool (llamado "foobar") indicándole los devices que estarán en el:
tokyo # zpool create foobar raidz2 /dev/md{1,2,3,4,5}
Podemos verificar que todo fue creado de manera correcta utilizando zpool status:
tokyo # zpool status
pool: foobar
state: ONLINE
scrub: none requested
config:
  NAME        STATE     READ WRITE CKSUM
  foobar      ONLINE       0     0     0
    raidz2    ONLINE       0     0     0
      md1     ONLINE       0     0     0
      md2     ONLINE       0     0     0
      md3     ONLINE       0     0     0
      md4     ONLINE       0     0     0
      md5     ONLINE       0     0     0
errors: No known data errors
Bien, ahora procederemos a crear los filesystems utilizando los dos tipos de compresión soportados por ZFS: lzjb y gzip. En este ejemplo crearemos primero un filesystem sin compresión para poder diferenciar entre el uso de esta y el no uso. Para especificar la algoritmo de compresión a utilizar debemos pasarle con -o el parámetro compression=<lzjb|gzip-0-9|off>.
tokyo # zfs create -o compression=off foobar/filesystem1
tokyo # zfs create -o compression=lzjb foobar/filesystem2
tokyo # zfs create -o compression=gzip-9 foobar/filesystem3
En este caso, creamos los 3 filesystems. El primero (filesystem1) sin utilizar compresión alguna, el segundo (filesystem2) utilizando lzjb y el tercero (filesystem3) utilizando gzip un ratio de 9 (mayor compresión posible). 
Estos ya se encuentran montados y dentro del directorio /foobar (el nombre del pool) y no necesitan ser añadidos al /etc/fstab (FreeBSD) o /etc/vfstab (en el caso de Solaris). 
Podemos comprobar la correcta creación de los mismos haciendo un zfs list:
tokyo # zfs list
NAME                 USED  AVAIL  REFER  MOUNTPOINT
foobar               281K   549M  42.9K  /foobar
foobar/filesystem1  37.5K   549M  37.5K  /foobar/filesystem1
foobar/filesystem2  37.5K   549M  37.5K  /foobar/filesystem2
foobar/filesystem3  37.5K   549M  37.5K  /foobar/filesystem3
En el directorio /tmp, cuento con un archivo llamado foobar.tar de unos 56Mb, vamos a copiar este a los tres filesystem que acabamos de crear para ver como se comportan:
tokyo # du -sh /tmp/foobar.tar
 56M  foobar.tar
tokyo # cp foobar.tar /foobar/filesystem1/
tokyo # cp foobar.tar /foobar/filesystem2/
tokyo # cp foobar.tar /foobar/filesystem3/
Una vez listo esto, podemos mirar cuanto pesa cada filesystem con el mismo archivo copiado en cada uno.
tokyo # du -sh /foobar/filesystem{1,2,3}
 56M  /foobar/filesystem1
 18M  /foobar/filesystem2
7.1M  /foobar/filesystem3
En el primer caso, sin compresión el filesystem pesa exactamente el tamaño del archivo foobar.tar 56M, en el segundo caso utilizando lzjb, pesa 18M (38M menos), y en el tercer caso utilizando gzip con un ratio de compresión de 9, el mismo pesa solo 7.1M (48.9M menos).
Ahora saquen sus propias conclusiones sobre uno de los increibles features con los que cuenta ZFS!.

2 comentarios:

  1. Me parece copado el test, ahora, podrias poner algun test de performances y de uso de CPU?

    Por ejemplo copiando algun archivo grande leido desde algun disco virtual en memoria hacia una particion primero sin compresion y luego con compresion, para ver si teniendo una CPU potente en verdad se podria ganar algo de velocidad usando un filesystem comprimido..

    Gracias!

    Todo esto me hace acordar a cuando era chico y usaba el STACKER en DOS para poder tener mas espacio en mi disco seagate de 47Mb! :)

    ResponderEliminar
  2. Dale, veo si puedo armar algo y lo publico.

    ResponderEliminar