domingo, 24 de agosto de 2014

Gluster: explotando su cache

Ya que los últimos días estuve trabajando bastante con gluster y su cache, me pareció interesante plasmarlo acá (para cuando me vuelva a olvidar cómo se hace ja!). La idea es mostrarles cómo se configura la cache en los volúmenes de gluster y qué funcionamiento tiene.

En este escenario vamos a estar trabajando con Gluster 3.5.2 (not production ready yet, but good enough :P) sobre CentOS 6.5.

Creando un volumen con  replica 2

Para empezar necesitamos crear un volumen. En este caso creamos un volumen con réplica 2 de la siguiente manera:

[root@gluster-test-1 ~]# gluster vol create volumen_prueba replica 2 gluster-test-1:/ladrillos/l1/l gluster-test-2:/ladrillos/l1/l
volume create: volumen_prueba: success: please start the volume to access data
[root@gluster-test-1 ~]# gluster vol start volumen_prueba
volume start: volumen_prueba: success
[root@gluster-test-1 ~]# 

Una vez creado e iniciado vemos su estado e información

[root@gluster-test-1 ~]# gluster vol status volumen_prueba
Status of volume: volumen_prueba
Gluster process                                         Port    Online  Pid
------------------------------------------------------------------------------
Brick gluster-test-1:/ladrillos/l1/l                    49159   Y       11717
Brick gluster-test-2:/ladrillos/l1/l                    49159   Y       12102
NFS Server on localhost                                 N/A     N       N/A
Self-heal Daemon on localhost                           N/A     Y       11731
NFS Server on gluster-test-3                            N/A     N       N/A
Self-heal Daemon on gluster-test-3                      N/A     Y       11929
NFS Server on gluster-test-2                            N/A     N       N/A
Self-heal Daemon on gluster-test-2                      N/A     Y       12120
 
Task Status of Volume volumen_prueba
------------------------------------------------------------------------------
There are no active volume tasks
 
[root@gluster-test-1 ~]# gluster vol info volumen_prueba
                                                                                                                                                                  
Volume Name: volumen_prueba                                                                                                                                       
Type: Replicate                                                                                                                                                   
Volume ID: 1197881d-ce2a-4f64-af17-53e5529b691c                                                                                                                   
Status: Started                                                                                                                                                   
Number of Bricks: 1 x 2 = 2                                                                                                                                       
Transport-type: tcp                                                                                                                                               
Bricks:                                                                                                                                                           
Brick1: gluster-test-1:/ladrillos/l1/l                                                                                                                            
Brick2: gluster-test-2:/ladrillos/l1/l                                                                                                                            
[root@gluster-test-1 ~]#   

Ahora que vemos que todo se encuentra bien montamos el volumen desde la máquina cliente:

[root@gluster-client-1 ~]# mount.glusterfs gluster-test-1:/volumen_prueba /mnt/gluster_vol                                                                       
[root@gluster-client-1 ~]# 

Dado que el montaje fue exitoso vemos los logs en /var/log/gluster/mnt-gluster_vol.log y encontramos la definición del volumen (todos estos translators y demás valores se cargan por defecto):

Final graph:
+------------------------------------------------------------------------------+
  1: volume volumen_prueba-client-0
  2:     type protocol/client
  3:     option remote-host gluster-test-1
  4:     option remote-subvolume /ladrillos/l1/l
  5:     option transport-type socket
  6:     option send-gids true
  7: end-volume
  8: 
  9: volume volumen_prueba-client-1
 10:     type protocol/client
 11:     option remote-host gluster-test-2
 12:     option remote-subvolume /ladrillos/l1/l
 13:     option transport-type socket
 14:     option send-gids true
 15: end-volume
 16: 
 17: volume volumen_prueba-replicate-0
 18:     type cluster/replicate
 19:     subvolumes volumen_prueba-client-0 volumen_prueba-client-1
 20: end-volume
 21: 
 22: volume volumen_prueba-dht
 23:     type cluster/distribute
 24:     subvolumes volumen_prueba-replicate-0
 25: end-volume
 26: 
 27: volume volumen_prueba-write-behind
 28:     type performance/write-behind
 29:     subvolumes volumen_prueba-dht
 30: end-volume
 31: 
 32: volume volumen_prueba-read-ahead
 33:     type performance/read-ahead
 34:     subvolumes volumen_prueba-write-behind
 35: end-volume
 36: 
 37: volume volumen_prueba-io-cache
 38:     type performance/io-cache
 39:     subvolumes volumen_prueba-read-ahead
 40: end-volume
 41: 
 42: volume volumen_prueba-quick-read
 43:     type performance/quick-read
 44:     subvolumes volumen_prueba-io-cache
 45: end-volume
 46: 
 47: volume volumen_prueba-open-behind
 48:     type performance/open-behind
 49:     subvolumes volumen_prueba-quick-read
 50: end-volume
 51: 
 52: volume volumen_prueba-md-cache
 53:     type performance/md-cache
 54:     subvolumes volumen_prueba-open-behind
 55: end-volume
 56: 
 57: volume volumen_prueba
 58:     type debug/io-stats
 59:     option latency-measurement off
 60:     option count-fop-hits off
 61:     subvolumes volumen_prueba-md-cache
 62: end-volume
 63: 
+------------------------------------------------------------------------------+

Las líneas 37 a 40 hacen referencia a la configuración del performance/IO-cache translator, el cuál se encarga de definir la configuración del cache del volumen.  Como vemos no hay demasiado configurado dado que aún se encuentra todo por defecto. Según la documentación oficial el tamaño default del cache es de 32Mbytes y un tiempo de expiración de 1 segundo. 

Algunos de los parámetros que podremos controlar desde aquí son:

  • cache-size: espacio asignado a cache
  • cache-timeout: tiempo de expiración de los objetos en cache
  • priority: permite asignar prioridades a distintos tipos de archivos para el uso de cache
  • cache-max-file-size: tamaño máximo de archivo que se puede almacenar en cache
  • cache-min-file-size: tamaño mínimo de archivo que se puede almacenar en cache

Probando los default settings:

Ahora que montamos el archivo vamos a probar la configuración por defecto con que se arman los volúmenes en gluster.

Primero escribimos un archivo de 25Mbytes en el directorio montado:

[root@gluster-client-1 ~]# dd if=/dev/zero of=/mnt/gluster_vol/25MB bs=1M count=25
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0286961 s, 914 MB/s
[root@gluster-client-1 ~]# ll -h /mnt/gluster_vol/
total 25M
-rw-r--r--. 1 root root 25M ago 24 20:54 25MB
[root@gluster-client-1 ~]# 

Ahora lo leeremos con intervalos de 10 segundos limpiando los bufferes del sistema entre cada operación:

[root@gluster-client-1 ~]# for i in 1 2 3 4 5; do echo 3 > /proc/sys/vm/drop_caches; dd of=/dev/null if=/mnt/gluster_vol/25MB bs=1M; date; sleep 10;done
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,271792 s, 96,5 MB/s
dom ago 24 21:20:12 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0568677 s, 461 MB/s
dom ago 24 21:20:22 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0402717 s, 651 MB/s
dom ago 24 21:20:32 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0392092 s, 669 MB/s
dom ago 24 21:20:43 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0420014 s, 624 MB/s
dom ago 24 21:20:53 ART 2014
[root@gluster-client-1 ~]# 

Interesante! La primer lectura demora 0.27 segundos, mientras que las 4 siguientes demoran entre 0.03 y 0.05! Claramente se trata de la intervención de la cache. Podría parecer confuso por los 10 segundos que esperamos entre lectura y lectura, pero la documentación define cache-timeout como un tiempo de expiración que fuerza una de re-validación, así que este es un comportamiento esperable. Probablemente estos 10 segundos de espera hubiesen sido demasiado en un entorno de mayor uso del cache.
 
Ahora corremos la misma prueba pero removiendo el tiempo de espera de 10 segundos:

[root@gluster-client-1 ~]# for i in 1 2 3 4 5; do echo 3 > /proc/sys/vm/drop_caches; dd of=/dev/null if=/mnt/gluster_vol/25MB bs=1M; date; done
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0485229 s, 540 MB/s
dom ago 24 21:25:18 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0471389 s, 556 MB/s
dom ago 24 21:25:18 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0360902 s, 726 MB/s
dom ago 24 21:25:18 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0359891 s, 728 MB/s
dom ago 24 21:25:18 ART 2014
25+0 records in
25+0 records out
26214400 bytes (26 MB) copied, 0,0355376 s, 738 MB/s
dom ago 24 21:25:18 ART 2014
[root@gluster-client-1 ~]# 

Podemos ver que los tiempos no son demasiado diferentes a los que obtuvimos anteriormente. 

Qué pasaría con un archivo mayor a 32Mbytes...? Escribimos un archivo de 128Mbytes para ver qué sucede:

[root@gluster-client-1 ~]# dd if=/dev/zero of=/mnt/gluster_vol/128MB bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 2,403 s, 55,9 MB/s
[root@gluster-client-1 ~]# ll -h /mnt/gluster_vol/
total 153M
-rw-r--r--. 1 root root 128M ago 24 21:27 128MB
-rw-r--r--. 1 root root  25M ago 24 21:19 25MB
[root@gluster-client-1 ~]# 

Ahora lo leemos:

[root@gluster-client-1 ~]# for i in 1 2 3 4 5; do echo 3 > /proc/sys/vm/drop_caches; dd of=/dev/null if=/mnt/gluster_vol/128MB bs=1M; date; done
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,95299 s, 68,7 MB/s
dom ago 24 21:29:09 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,95518 s, 68,6 MB/s
dom ago 24 21:29:11 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,96224 s, 68,4 MB/s
dom ago 24 21:29:13 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,94886 s, 68,9 MB/s
dom ago 24 21:29:15 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,98702 s, 67,5 MB/s
dom ago 24 21:29:17 ART 2014
[root@gluster-client-1 ~]#

En este caso vemos claramente que estamos teniendo velocidades de lectura muy bajas, lo que nos da la pauta de que no estamos utilizando la cache.

Modificando la configuración de cache:

Ahora vamos a aumentar nuestra capacidad de cache para lograr una buena velocidad de lectura en el caso del archivo de 128Mbytes. Seteamos la cache a 256Mbytes de la siguiente manera:

[root@gluster-test-1 ~]# gluster vol set volumen_prueba performance.cache-size 256MB                                                                             
volume set: success                                                                                                                                               
[root@gluster-test-1 ~]# gluster vol info volumen_prueba
Volume Name: volumen_prueba
Type: Replicate
Volume ID: 1197881d-ce2a-4f64-af17-53e5529b691c
Status: Started
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: gluster-test-1:/ladrillos/l1/l
Brick2: gluster-test-2:/ladrillos/l1/l
Options Reconfigured:
performance.cache-size: 256MB
[root@gluster-test-1 ~]# 

Podríamos pensar que no sucedió nada, pero...

[root@gluster-client-1 ~]# for i in 1 2 3 4 5; do echo 3 > /proc/sys/vm/drop_caches; dd of=/dev/null if=/mnt/gluster_vol/128MB bs=1M; date; done
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,59836 s, 84,0 MB/s
dom ago 24 21:34:25 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1,26796 s, 106 MB/s
dom ago 24 21:34:26 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 0,159935 s, 839 MB/s
dom ago 24 21:34:26 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 0,152958 s, 877 MB/s
dom ago 24 21:34:27 ART 2014
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 0,164556 s, 816 MB/s
dom ago 24 21:34:27 ART 2014
[root@gluster-client-1 ~]# 

Sin necesidad de reiniciar absolútamente nada, ni de desmontar el volumen, vemos como gluster fue capaz de reconocer el aumento del tamaño de cache y permitirnos leer el archivo de 128Mbytes hasta mas de 10 veces mas rápido!!!

El resto es cuento, solo hay que ponerse a jugar con los valores para obtener la política de cache que uno quiere. 

Dónde se almacena la cache?

Hice un par de preguntas al respecto en la lista de usuarios de gluster, dado que no me quedaba del todo claro dónde se almacena la cache. Según la documentación el translator performance/io-cache puede encontrarse presente tanto en el servidor como en el cliente con objetivos distintos. 
  • Estando en el servidor permite compartir la cache con varios clientes de manera simultánea.
  • Estando en el cliente permite ahorrar ancho de banda y CPU (del servidor).
En la lista me dijieron que el translator performance/io-cache se carga durante el proceso de montado del volumen así que la cache por defecto se encuentra en el cliente.

No hay comentarios:

Publicar un comentario