O sistema de arquivos é nossa forma de armazenamento comum, composta principalmente de duas partes: dados e metadados. Entre eles, os dados são o conteúdo específico do arquivo, que geralmente é exibido diretamente para o usuário; e os metadados são os dados que descrevem os dados, que são usados para registrar atributos do arquivo, estrutura de diretórios, local de armazenamento de dados etc. De um modo geral, os metadados têm características muito distintas, ou seja, ocupam menos espaço, mas são acessados com muita frequência.
Nos sistemas de arquivos distribuídos de hoje, alguns (como o S3FS) gerenciam metadados e dados de maneira unificada para simplificar o design do sistema, mas a desvantagem é que algumas operações de metadados farão com que os usuários experimentem atrasos óbvios, como diretórios ls
grandes etc. Mais sistemas de arquivos optarão por gerenciar os dois separadamente e executar a otimização direcionada de acordo com as características dos metadados. O JuiceFS adota esse design e seu diagrama de arquitetura é o seguinte:
Entre eles, o mecanismo de metadados precisa ser um banco de dados que suporte operações de transação, e o mecanismo de dados geralmente usa armazenamento de objetos . Até agora, o JuiceFS suportou mais de 10 mecanismos de metadados e mais de 30 mecanismos de dados.
Ao usar o JuiceFS, os usuários podem escolher livremente componentes maduros para atuar como esses dois mecanismos para lidar com ambientes corporativos ricos e mutáveis e requisitos de armazenamento de dados. No entanto, para novos usuários, quando se deparam com mais opções, também surge uma pergunta: Qual banco de dados é mais apropriado para escolher como mecanismo de metadados em meu cenário? Este artigo apresentará os tipos de mecanismos de metadados que o JuiceFS pode usar, bem como suas vantagens e desvantagens do ponto de vista do design do produto.
01-JuiceFS tipo de mecanismo de metadados
Existem três categorias de mecanismos de metadados atualmente suportados pelo JuiceFS.
O primeiro é o Redis . Redis é o mecanismo de metadados mais antigo suportado pelo JuiceFS depois que ele foi aberto. Em primeiro lugar, o Redis é rápido o suficiente, que é um dos recursos importantes que os mecanismos de metadados precisam ter; em segundo lugar, o Redis tem um público amplo e a maioria dos usuários tem experiência prática no Redis. O JuiceFS também oferece suporte a bancos de dados compatíveis com o protocolo Redis, como KeyDB e Amazon MemoryDB.
No entanto, a confiabilidade e a escalabilidade do Redis são facilmente limitadas e seu desempenho é fraco em alguns cenários com altos requisitos de segurança de dados ou grande escala. Portanto, desenvolvemos e suportamos dois outros tipos de mecanismos.
A segunda é a classe SQL . Como MySQL, MariaDB, PostgreSQL, etc., eles são caracterizados por alta popularidade e geralmente possuem boa confiabilidade e escalabilidade. Além disso, o banco de dados embutido SQLite também é suportado.
A última é a classe TKV (Transactional Key-Value Database) . Suas interfaces nativas são relativamente simples, por isso são mais personalizáveis no JuiceFS e geralmente têm desempenho superior ao das classes SQL. No momento, esse tipo de suporte inclui TiKV, etcd e BadgerDB incorporado, etc. O suporte para FoundationDB também está em desenvolvimento intensivo.
A classificação acima é baseada na interface de protocolo do JuiceFS ao se conectar ao banco de dados. Existem vários bancos de dados em cada categoria, e cada banco de dados tem suas próprias características. A seguir, comparamos várias opções comumente usadas pelos usuários com base nessas características.
Comparação do Mecanismo de Metadados
Redis | MySQL/PostgreSQL | TiKV | etcd | SQLite/BadgerDB | |
---|---|---|---|---|---|
desempenho | alto | Baixo | meio | Baixo | meio |
Escalabilidade | Baixo | meio | alto | Baixo | Baixo |
confiabilidade | Baixo | alto | alto | alto | meio |
disponibilidade | meio | alto | alto | alto | Baixo |
Popularidade | alto | alto | meio | alto | meio |
Como mencionado acima, a maior vantagem do Redis é seu alto desempenho, por ser um banco de dados com memória total. Em outros aspectos, é medíocre.
Em termos de escalabilidade, geralmente um único Redis pode suportar cerca de 100 milhões de arquivos. Quando ultrapassar 100 milhões, o uso de memória de um único processo Redis será relativamente grande e o desempenho do gerenciamento também diminuirá. A versão de código aberto do Redis oferece suporte ao modo cluster para expandir a quantidade total de dados que pode gerenciar. No entanto, como o Redis não oferece suporte a transações distribuídas no modo cluster, como o mecanismo de metadados JuiceFS, ainda há apenas um processo Redis disponível para cada JuiceFS volume. , a escalabilidade de um único volume não é muito aprimorada em comparação com um único Redis.
Do ponto de vista da confiabilidade, o Redis libera dados a cada segundo por padrão, o que pode causar uma pequena perda de dados em caso de exceção. Ao alterar a configuração do appendfsync para sempre, o Redis pode ser liberado após cada solicitação de gravação, para que o desempenho da confiabilidade dos dados seja aprimorado, mas o desempenho diminuirá.
Em termos de disponibilidade, a implantação de nós de monitoramento sentinela Redis e nós de espera pode selecionar um nó de backup para fornecer serviços novamente após o nó principal do Redis desligar, melhorando a disponibilidade até certo ponto. No entanto, o próprio Redis não oferece suporte a um protocolo de consenso distribuído e seus nós de backup usam backup assíncrono; portanto, embora o novo nó esteja ativo, pode haver lacunas de dados no meio, resultando em dados incompletos.
O desempenho geral do MySQL e do PostgreSQL é semelhante. Eles são todos produtos de banco de dados que foram verificados por um grande número de usuários por muitos anos, com boa confiabilidade e disponibilidade e alta popularidade. Só que seu desempenho é mediano em comparação com outros mecanismos de metadados.
TiKV era originalmente o armazenamento subjacente do PingCAP TiDB, mas agora foi separado e se tornou um componente de banco de dados KV independente. A partir de nossos resultados de teste, é uma excelente escolha para o mecanismo de metadados JuiceFS. Possui confiabilidade de dados e disponibilidade de serviço não mais fraca que o MySQL e tem melhor desempenho e escalabilidade. Apenas em termos de popularidade, ainda há uma lacuna entre ele e o MySQL. Pela nossa comunicação com os usuários, se eles já são usuários do TiKV ou TiDB, eles geralmente preferem usar o TiKV como mecanismo de metadados do JuiceFS no final. Mas se eles não estiverem familiarizados com o TiKV antes, serão muito mais cautelosos ao aceitar esse novo componente.
O etcd é outro banco de dados semelhante ao TKV. A razão para oferecer suporte ao etcd é porque ele é muito popular em cenários de conteinerização. Basicamente, o k8s usa o etcd para gerenciar sua configuração. Usar o etcd como mecanismo de metadados do JuiceFS não é um cenário particularmente adequado. Por um lado, seu desempenho é mediano e, por outro, possui limitações de capacidade (padrão 2G, máximo 8G) e será difícil expandir posteriormente. No entanto, sua confiabilidade e disponibilidade são muito altas e é fácil de implantar em cenários conteinerizados. Portanto, se os usuários precisarem apenas de um sistema de arquivos com escala de um milhão de arquivos, o etcd ainda é uma boa escolha .
Finalmente, há o SQLite e o BadgerDB, que pertencem à classe SQL e à classe TKV, respectivamente, mas a experiência de usá-los é muito semelhante, porque são todos bancos de dados embutidos autônomos. Esse tipo de banco de dados é caracterizado por desempenho médio, mas baixa escalabilidade e disponibilidade, pois seus dados são realmente armazenados no sistema local. Eles têm a vantagem de serem muito fáceis de usar, exigindo apenas os próprios binários do JuiceFS e nenhum componente adicional. Os usuários podem usar esses dois bancos de dados em determinados cenários específicos ou ao realizar alguns testes funcionais simples.
02- Resultados do teste de desempenho de um motor típico
Fizemos alguns testes típicos de desempenho do motor e registramos os resultados neste documento . Um dos resultados mais diretos do teste de interface de origem é aproximadamente: Redis > TiKV (3 cópias) > MySQL (local) ~= etcd (3 cópias) , como segue:
Redis-Always | Redis-EverysecName | TiKV | MySQL | etcd | |
---|---|---|---|---|---|
mkdir | 600 | 471 (0,8) | 1614 (2.7) | 2121 (3,5) | 2203 (3,7) |
é mv | 878 | 756 (0,9) | 1854 (2.1) | 3372 (3,8) | 3000 (3,4) |
é rm | 785 | 673 (0,9) | 2097 (2.7) | 3065 (3,9) | 3634 (4,6) |
readdir_10 | 302 | 303 (1,0) | 1232 (4.1) | 1011 (3.3) | 2171 (7,2) |
readdir_1k | 1668 | 1838 (1.1) | 6682 (4.0) | 16824 (10.1) | 17470 (10,5) |
mknod | 584 | 498 (0,9) | 1561 (2,7) | 2117 (3.6) | 2232 (3,8) |
criar | 591 | 468 (0,8) | 1565 (2.6) | 2120 (3,6) | 2206 (3,7) |
renomear | 860 | 736 (0,9) | 1799 (2.1) | 3391 (3,9) | 2941 (3,4) |
desvincular | 709 | 580 (0,8) | 1881 (2.7) | 3052 (4.3) | 3080 (4.3) |
olho para cima | 99 | 97 (1,0) | 731 (7.4) | 423 (4.3) | 1286 (13,0) |
getattr | 91 | 89 (1,0) | 371 (4.1) | 343 (3,8) | 661 (7,3) |
setattr | 501 | 357 (0,7) | 1358 (2,7) | 1258 (2,5) | 1480 (3,0) |
acesso | 90 | 89 (1,0) | 370 (4.1) | 348 (3,9) | 646 (7.2) |
setxattr | 404 | 270 (0,7) | 1116 (2,8) | 1152 (2,9) | 757 (1,9) |
getxattr | 91 | 89 (1,0) | 365 (4,0) | 298 (3,3) | 655 (7,2) |
removexattr | 219 | 95 (0,4) | 1554 (7.1) | 882 (4,0) | 1461 (6,7) |
listxattr_1 | 88 | 88 (1,0) | 374 (4.2) | 312 (3,5) | 658 (7,5) |
listxattr_10 | 94 | 91 (1,0) | 390 (4.1) | 397 (4.2) | 694 (7,4) |
link | 605 | 461 (0,8) | 1627 (2.7) | 2436 (4,0) | 2237 (3,7) |
link simbólico | 602 | 465 (0,8) | 1633 (2.7) | 2394 (4,0) | 2244 (3,7) |
escrever | 613 | 371 (0,6) | 1905 (3.1) | 2565 (4.2) | 2350 (3,8) |
ler_1 | 0 | 0 (0,0) | 0 (0,0) | 0 (0,0) | 0 (0,0) |
ler_10 | 0 | 0 (0,0) | 0 (0,0) | 0 (0,0) | 0 (0,0) |
- A tabela acima registra o consumo de tempo de cada operação, quanto menor o valor, melhor; o número entre colchetes é o múltiplo do índice comparado ao Redis-always, e quanto menor o valor, melhor
- Always e Everysec são valores opcionais do item de configuração do Redis appendfsync, que indicam respectivamente que cada solicitação é liberada e cada segundo é liberado
- Percebe-se que quando o Redis usa o everysec, seu desempenho é melhor, mas não muito diferente de sempre; isso porque o desempenho de IOPS do próprio disco SSD local na máquina AWS usada para o teste é relativamente alto
- Tanto o TiKV quanto o etcd usam três cópias, enquanto o MySQL é implantado em uma única máquina. Mesmo assim, o desempenho do TiKV ainda é superior ao do MySQL, enquanto o etcd está próximo do MySQL.
Vale ressaltar que todos os testes acima usam configurações padrão, e nenhum ajuste específico foi feito para cada mecanismo de metadados. Os usuários podem configurar e ajustar de acordo com suas próprias necessidades e experiência prática ao usá-lo, podendo haver resultados diferentes .
Outro teste foi executado através da ferramenta de bancada que acompanha o JuiceFS, que executa a interface do sistema operacional para leitura e gravação de arquivos. Os resultados específicos são os seguintes:
Redis-Always | Redis-EverysecName | TiKV | MySQL | etcd | |
---|---|---|---|---|---|
Gravar arquivo grande | 565,07 MiB/s | 556,92 MiB/s | 553,58 MiB/s | 557,93 MiB/s | 542,93 MiB/s |
Ler arquivo grande | 664,82 MiB/s | 652,18 MiB/s | 679,07 MiB/s | 673,55 MiB/s | 672,91 MiB/s |
Escreva um arquivo pequeno | 102,30 arquivos/s | 105,80 arquivos/s | 95,00 arquivos/s | 87,20 arquivos/s | 95,75 arquivos/s |
Ler arquivo pequeno | 2200,30 arquivos/s | 1894,45 arquivos/s | 1394,90 arquivos/s | 1360,85 arquivos/s | 1017,30 arquivos/s |
Arquivo de estatísticas | 11607.40 arquivos/s | 15032.90 arquivos/s | 3283.20 files/s | 5470.05 files/s | 2827.80 files/s |
FUSE operation | 0.41 ms/op | 0.42 ms/op | 0.45 ms/op | 0.46 ms/op | 0.42 ms/op |
Update meta | 3.63 ms/op | 3.19 ms/op | 7.04 ms/op | 8.91 ms/op | 4.46 ms/op |
从上表可以看到,读写大文件时使用不同的元数据引擎最后性能是差不多的。这是因为此时性能瓶颈主要在对象存储的数据读写上,元数据引擎之间虽然时延有点差异,但是放到整个业务读写的消耗上,这点差异几乎可以忽略不计。当然,如果对象存储变得非常快(比如都用本地全闪部署),那么元数据引擎的性能差异可能又会体现出来。另外,对于一些纯元数据操作(比如 ls,创建空文件等),不同元数据引擎的性能差别也会表现的比较明显。
03-引擎选型的考虑要素
根据上文介绍的各引擎特点,用户可以根据自己的情况去选择合适的引擎。以下简单分享下我们在做推荐时会建议用户考虑的几个要素。
评估需求:比如想使用 Redis,需要先评估能否接受少量的数据丢失,短期的服务中断等。如果是存储一些临时数据或者中间数据的场景,那么用 Redis 确实是不错的选择,因为它性能够好,即使有少量的数据丢失,也不会造成很大的影响。但如果是要存储一些关键数据, Redis 就不适用了。另外还得评估预期数据的规模,如果在 1 亿文件左右, Redis 可以承受;如果预期会有 10 亿文件,那么显然单机 Redis 是难以承载的。
评估硬件:比如能否连通外网,是使用托管的云服务,还是在自己机房内私有部署。如果是私有部署,需要评估是否有足够的硬件资源去部署一些相关的组件。无论是用哪一种元数据引擎,基本上都要求有高速的 SSD 盘去运行,不然会对其性能有比较大的影响。
评估运维能力,这是很多人会忽视的,但是在我们来看这应该是最关键的因素之一。对于存储系统来说,稳定性往往才是其上生产后的第一重点。用户在选择元数据引擎的时候,应该先想想自己对它是不是熟悉,在出现问题时,能否快速定位解决;团队内是否有足够的经验或精力去把控好这个组件。通常来说,我们会建议用户在开始时选择一个自己熟悉的数据库是比较合适的。如果运维人员不足,那么选择 JuiceFS 公有云服务也确实是个省心的选项。
最后,分享下社区在使用元数据引擎方面的一些统计数据。
- 目前为止, Redis 的使用者依然占了一半以上,其次是 TiKV 和 MySQL,这两类的使用者的数量占比在逐步增长。
- 在运行的 Redis 集群的最大文件数大概是在 1.5 亿,而且运行情况是比较稳定的,上文提到的推荐的 1 亿文件是建议值,并不是说无法超过 1 亿。
- 整体数量规模 Top3,都是使用的 TiKV 而且都超过了 10 亿文件数量。现在最大的文件系统的文件数量是超了 70 亿文件,总容量超过了 15 PiB,这也从侧面证明了 TiKV 在作为元数据引擎时的扩展能力。我们自己内部测过使用 TiKV 作为元数据引擎存储 100 亿文件,系统仍能稳定地运行。所以如果你的整个集群预期的规模会非常大,那么TiKV 确实是一个很好的选择。
04- 元数引擎迁移
文章的最后,为大家介绍元数据引擎迁移。 随着用户业务的发展,企业对元数据引擎的需求会发生变化,当用户发现现有的元数据引擎不合适了,可以考虑将元数据迁移到另一个引擎中。 我们为用户提供了完整的迁移方法,具体可以参考这个文档。
这个迁移方法有一定的限制,首先只能迁移到空数据库,暂时无法将两个文件系统直接合在一起;其次,需要停写,因为数据量会比较大的情况下,很难在线将元数据完整的迁移过来。要做到这点需要加许多限制,从实测来看速度会非常慢。因此,把整个文件系统停掉再去做迁移是最稳妥的。如果说实在需要有一定的服务提供,可以保留只读挂载,用户读数据并不会影响整个元数据引擎迁移的动作。
虽然社区提供了全套的迁移方法,但是还是需要提醒用户,尽量提前对数据量的增长做好规划,尽量不做迁移或尽早迁移。当要迁移的数据规模很大时,耗时也会变长,期间出问题的概率也会变大。
如有帮助的话欢迎关注我们项目 Juicedata/JuiceFS 哟! (0ᴗ0✿)