O LVM cache é um novo recurso do LVM que permite criar um volume lógico com um dispositivo mais rápido e capacidade reduzida (por exemplo, um disco SSD) para ser usado como cache para um dispositivo com maior capacidade, porém, mais lento, aumentando significativamente o desempenho dos sistemas de arquivos em cargas de I/O específicas e mantendo a capacidade de armazenamento dos discos magnéticos tradicionais.
Esta funcionalidade foi introduzida como Technology Preview no Red Hat Enterprise Linux 7 e é baseado no dm-cache. Essencialmente, o dm-cache usa o device mapper para adicionar uma camada onde são definidas as políticas para controle do cache (quais dados devem ser armazenados no cache e por quanto tempo).
Quando configurado para usar a política padrão multiqueue, o dm-cache usa o disco SSD para armazenar os dados associados às operações randômicas de leitura e escrita, aproveitando os baixos tempos de latência destes discos e evitando tais operações nos discos tradicionais – geralmente uma das principais causas de gargalo. Os dados associados às operações sequenciais não são armazenados no disco SSD para evitar a invalidação do cache; este tipo de operação é muito mais adequado nos discos tradicionais e, além disso, ele diminui a vida útil dos discos SSD.
Com relação ao modo de operação, o dm-cache atualmente suporta dois: write-back (padrão) e o write-through.
- Write-back cache é quando a operação de escrita é enviada diretamente para o cache e a resposta é imediatamente enviada para o sistema. Isto resulta em baixa latência e aumento da largura de banda para aplicações que executam muitas operações de escrita. Entretanto, como as cópias dos dados alterados ficam armazenadas apenas no cache durante um determinado momento, existe o risco de perda destes dados em caso de falha. O write-back é a solução com melhor desempenho para cargas de trabalho onde a quantidade de operações de escrita e leitura são próximas e exigem tempos de resposta equivalentes.
- Write-through cache envia as operações de escrita simultaneamente para o cache e para a camada de storage permanente, aguardando sua conclusão antes de enviar a resposta para o sistema. Isto garante segurança aos dados sob a desvantagem de manter a mesma latência nas operações de escrita. Este método é interessante para aplicações que gravam e depois fazem a releitura dos dados com frequência, já que os dados armazenados no cache resultam em baixa latência para a leitura.
Configuração
Ainda existe pouca informação sobre o cache na página de manual do lvm(8), mas os exemplos existentes são suficientes quando não se quer fazer uma configuração muito complexa. A seguir veremos como criar uma configuração padrão de volumes LVM com cache em um sistema Red Hat Enterprise Linux 7.0.
Primeiramente, para possibilitarmos a configuração, apresentamos dois novos discos para o sistema operacional: /dev/sdb com 20 GB e /dev/sdc com 5 GB.
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 8G 0 disk
├─sda1 8:1 0 500M 0 part /boot
└─sda2 8:2 0 7.5G 0 part
├─rhel-root 253:0 0 6.7G 0 lvm /
└─rhel-swap 253:1 0 820M 0 lvm [SWAP]
sdb 8:16 0 20G 0 disk
sdc 8:32 0 5G 0 disk
Ambos os dispositivos são virtuais e estão localizados em um disco tradicional, entretanto, para os nossos exemplos de configuração, iremos supor que o dispositivo /dev/sdb representa um disco tradicional e o /dev/sdc um disco SSD.
Em seguida, criamos o Volume Group chamado vg_cache contendo ambos os discos.
Physical volume “/dev/sdb” successfully created
Physical volume “/dev/sdc” successfully created
Volume group “vg_cache” successfully created
O próximo passo é criar os volumes lógicos. São necessários três:
- OriginLV: o volume lógico criado no dispositivo mais lento, onde estará localizado o sistema de arquivos para armazenar os dados.
- CacheDataLV: o volume lógico criado no dispositivo mais rápido, onde serão armazenados os dados do cache.
- CacheMetaLV: outro volume lógico criado no dispositivo mais rápido, usado para armazenar informações sobre a localização dos blocos no cache e outras informações internas para funcionamento das políticas de armazenamento. A documentação recomenda que seu tamanho seja no mínimo 1/1000 do tamanho do dispositivo CacheDataLV.
Com os comandos a seguir, criamos o OriginLV com 15 GB chamado lv_data e localizado no dispositivo /dev/sdb, o CacheDataLV com 3 GB chamado lv_cache no dispositivo /dev/sdc e o dispositivo CacheMetaLV com 256 MB chamado lv_meta_cache no dispositivo /dev/sdc.
Logical volume “lv_data” created
# lvcreate -L3G -n lv_cache vg_cache /dev/sdc
Logical volume “lv_cache” created
# lvcreate -L256M -n lv_meta_cache vg_cache /dev/sdc
Logical volume “lv_meta_cache” created
Um resumo das configurações do LVM até agora aplicadas.
PV VG Fmt Attr PSize PFree
/dev/sdb vg_cache lvm2 a– 20.00g 5.00g
/dev/sdc vg_cache lvm2 a– 5.00g 1.75g
# lvs
LV VG Attr LSize Pool Origin Data% Move Log Cpy%Sync Convert
lv_cache vg_cache -wi-a—– 3.00g
lv_data vg_cache -wi-a—– 15.00g
lv_meta_cache vg_cache -wi-a—– 256.00m
Agora configuramos o nosso Cache Pool, onde fazemos a associação entre os volumes lógicos específicos do cache (lv_cache e lv_meta_cache).
Logical volume “lvol0” created
Converted vg_cache/lv_cache to cache pool.
Configuramos o volume lógico de dados para usar o Cache Pool recém-criado.
vg_cache/lv_data is now cached.
Note que no comando anterior o sistema confirmou que nosso volume lv_data agora está utilizando o cache. Executamos novamente os comandos para visualizarmos as configurações dos nossos volumes LVM.
PV VG Fmt Attr PSize PFree
/dev/sdb vg_cache lvm2 a– 20.00g 4.75g
/dev/sdc vg_cache lvm2 a– 5.00g 1.75g
# lvs
LV VG Attr LSize Pool Origin Data% Move Log Cpy%Sync Convert
lv_cache vg_cache Cwi-a-C— 3.00g
lv_data vg_cache Cwi-aoC— 15.00g lv_cache [lv_data_corig]
Por fim, podemos formatar nosso volume lógico lv_data com algum sistema de arquivos (por exemplo, XFS) e montá-lo para utilização (em nosso exemplo, no diretório /cached).
meta-data=/dev/vg_cache/lv_data isize=256 agcount=16, agsize=245760 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0
data = bsize=4096 blocks=3932160, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
# mkdir /cached
# mount /dev/vg_cache/lv_data /cached
Para visualizarmos o status do nosso volume com cache, usamos o comando dmsetup status.
0 31457280 cache 8 107/65536 128 185/49152 893 141 768 0 0 185 0 1 writeback 2
migration_threshold 2048 mq 10 random_threshold 4 sequential_threshold 512
discard_promote_adjustment 1 read_promote_adjustment 4 write_promote_adjustment 8
Os valores destacados em vermelho são, respectivamente, quantas operações de leitura que foram atendidas pelo cache (read cache hits) e quantas não foram encontradas no cache e precisaram ser lidas do disco tradicional (read cache misses). Os outros dois valores são para as operações de escrita.
Em azul está destacado o modo de operação atual do cache (write-back). Esta configuração não pode ser alterada em tempo de execução para o modo write-through. Neste caso, faz-se necessário recriar o Cache Pool utilizando a opção:
Nota sobre Benchmarks
Como na configuração realizada no exemplo acima não existia disco SSD, não foi possível realizarmos testes de desempenho para compararmos com outras configurações.
Devido as particularidades da política multiqueue, já discutidas anteriormente, os benchmarks que priorizam as operações sequenciais tendem a não apresentar nenhuma diferença quando executados em um volume com LVM Cache. Portanto, para conseguir visualizar algum ganho de desempenho, os benchmarks devem considerar apenas as operações randômicas.
Referências
Device-mapper Documentation. Device-mapper: Cache. Kernel.org. Acessado em 16-10-2014.
Edge, Jake (01-05-2013). LSFMM: Caching — dm-cache and bcache. LWN.net. Acessado em 17-10-2014.
Jones, Richard (22-05-2014). Using LVM’s new cache feature. Richard WM Jones. Acessado em 17-10-2014.