summaryrefslogtreecommitdiffstats
path: root/pt-br/news/phase4-storage-deduplication
diff options
context:
space:
mode:
Diffstat (limited to 'pt-br/news/phase4-storage-deduplication')
-rw-r--r--pt-br/news/phase4-storage-deduplication/index.html229
-rw-r--r--pt-br/news/phase4-storage-deduplication/index.html.gzbin0 -> 5097 bytes
2 files changed, 229 insertions, 0 deletions
diff --git a/pt-br/news/phase4-storage-deduplication/index.html b/pt-br/news/phase4-storage-deduplication/index.html
new file mode 100644
index 0000000..e927cfb
--- /dev/null
+++ b/pt-br/news/phase4-storage-deduplication/index.html
@@ -0,0 +1,229 @@
+<!DOCTYPE html>
+<html lang="pt-br">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Fase 4: Deduplicacao de Armazenamento — Tesseras</title>
+ <meta name="description" content="Uma nova camada de armazenamento enderecavel por conteudo elimina dados duplicados entre tesseras, reduzindo uso de disco e habilitando coleta de lixo automatica.">
+ <!-- Open Graph -->
+ <meta property="og:type" content="article">
+ <meta property="og:title" content="Fase 4: Deduplicacao de Armazenamento">
+ <meta property="og:description" content="Uma nova camada de armazenamento enderecavel por conteudo elimina dados duplicados entre tesseras, reduzindo uso de disco e habilitando coleta de lixo automatica.">
+ <meta property="og:image" content="https://tesseras.net/images/social.jpg">
+ <meta property="og:image:width" content="1200">
+ <meta property="og:image:height" content="630">
+ <meta property="og:site_name" content="Tesseras">
+ <!-- Twitter Card -->
+ <meta name="twitter:card" content="summary_large_image">
+ <meta name="twitter:title" content="Fase 4: Deduplicacao de Armazenamento">
+ <meta name="twitter:description" content="Uma nova camada de armazenamento enderecavel por conteudo elimina dados duplicados entre tesseras, reduzindo uso de disco e habilitando coleta de lixo automatica.">
+ <meta name="twitter:image" content="https://tesseras.net/images/social.jpg">
+ <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690">
+
+
+ <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml">
+
+
+ <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d">
+
+</head>
+<body>
+ <header>
+ <h1>
+ <a href="https:&#x2F;&#x2F;tesseras.net/pt-br/">
+ <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo">
+ Tesseras
+ </a>
+ </h1>
+ <nav>
+
+ <a href="https://tesseras.net/pt-br/about/">Sobre</a>
+ <a href="https://tesseras.net/pt-br/news/">Notícias</a>
+ <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a>
+ <a href="https://tesseras.net/pt-br/faq/">FAQ</a>
+ <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a>
+ <a href="https://tesseras.net/pt-br/contact/">Contato</a>
+
+ </nav>
+ <nav class="lang-switch">
+
+ <a href="https:&#x2F;&#x2F;tesseras.net&#x2F;news&#x2F;phase4-storage-deduplication&#x2F;">English</a> | <strong>Português</strong>
+
+ </nav>
+ </header>
+
+ <main>
+
+<article>
+ <h2>Fase 4: Deduplicacao de Armazenamento</h2>
+ <p class="news-date">2026-02-15</p>
+ <p>Quando multiplas tesseras compartilham a mesma foto, o mesmo clipe de audio ou
+os mesmos dados de fragmento, a camada de armazenamento antiga mantinha copias
+separadas de cada. Em um no armazenando milhares de tesseras para a rede, essa
+duplicacao se acumula rapidamente. A Fase 4 continua com deduplicacao de
+armazenamento: um armazenamento enderecavel por conteudo (CAS) que garante que
+cada dado unico seja armazenado exatamente uma vez em disco, independentemente
+de quantas tesseras o referenciam.</p>
+<p>O design e simples e comprovado: hash do conteudo com BLAKE3, usar o hash como
+nome do arquivo e manter uma contagem de referencias no SQLite. Quando duas
+tesseras incluem a mesma foto de 5 MB, um arquivo existe em disco com
+refcount 2. Quando uma tessera e deletada, o refcount cai para 1 e o arquivo
+permanece. Quando a ultima referencia e liberada, uma varredura periodica limpa
+o orfao.</p>
+<h2 id="o-que-foi-construido">O que foi construido</h2>
+<p><strong>Migracao do esquema CAS</strong> (<code>tesseras-storage/migrations/004_dedup.sql</code>) — Tres
+novas tabelas:</p>
+<ul>
+<li><code>cas_objects</code> — rastreia cada objeto no armazenamento: hash BLAKE3 (chave
+primaria), tamanho em bytes, contagem de referencias e timestamp de criacao</li>
+<li><code>blob_refs</code> — mapeia identificadores logicos de blobs (hash da tessera + hash
+da memoria + nome do arquivo) para hashes CAS, substituindo a convencao antiga
+de caminhos no sistema de arquivos</li>
+<li><code>fragment_refs</code> — mapeia identificadores logicos de fragmentos (hash da
+tessera + indice do fragmento) para hashes CAS, substituindo o antigo layout
+do diretorio <code>fragments/</code></li>
+</ul>
+<p>Indices nas colunas de hash garantem lookups O(1) durante leituras e contagem de
+referencias.</p>
+<p><strong>CasStore</strong> (<code>tesseras-storage/src/cas.rs</code>) — O motor central de armazenamento
+enderecavel por conteudo. Arquivos sao armazenados sob um diretorio de prefixo
+de dois niveis: <code>&lt;raiz&gt;/&lt;prefixo-hex-2-chars&gt;/&lt;hash-completo&gt;.blob</code>. O
+armazenamento fornece cinco operacoes:</p>
+<ul>
+<li><code>put(hash, data)</code> — escreve dados em disco se ainda nao presente, incrementa o
+refcount. Retorna se ocorreu um hit de deduplicacao.</li>
+<li><code>get(hash)</code> — le dados do disco pelo hash</li>
+<li><code>release(hash)</code> — decrementa o refcount. Se chegar a zero, o arquivo em disco
+e deletado imediatamente.</li>
+<li><code>contains(hash)</code> — verifica existencia sem ler</li>
+<li><code>ref_count(hash)</code> — retorna a contagem de referencias atual</li>
+</ul>
+<p>Todas as operacoes sao atomicas dentro de uma unica transacao SQLite. O refcount
+e a fonte de verdade — se o refcount diz que o objeto existe, o arquivo deve
+estar em disco.</p>
+<p><strong>FsBlobStore com CAS</strong> (<code>tesseras-storage/src/blob.rs</code>) — Reescrito para
+delegar todo armazenamento ao CAS. Quando um blob e escrito, seu hash BLAKE3 e
+computado e passado para <code>cas.put()</code>. Uma linha em <code>blob_refs</code> mapeia o caminho
+logico (tessera + memoria + arquivo) para o hash CAS. Leituras buscam o hash CAS
+via <code>blob_refs</code> e leem de <code>cas.get()</code>. Deletar uma tessera libera todas as suas
+referencias de blob em uma unica transacao.</p>
+<p><strong>FsFragmentStore com CAS</strong> (<code>tesseras-storage/src/fragment.rs</code>) — Mesmo padrao
+para fragmentos codificados com erasure coding. O checksum BLAKE3 de cada
+fragmento ja e computado durante a codificacao Reed-Solomon, entao e usado
+diretamente como chave CAS. A verificacao de fragmentos agora checa o hash CAS
+ao inves de recomputar do zero — se o CAS diz que os dados estao intactos,
+estao.</p>
+<p><strong>Coletor de lixo sweep</strong> (<code>cas.rs:sweep()</code>) — Uma passagem periodica de GC que
+trata tres casos limite que o caminho normal de refcount nao consegue:</p>
+<ol>
+<li><strong>Arquivos orfaos</strong> — arquivos em disco sem linha correspondente em
+<code>cas_objects</code>. Pode acontecer apos um crash durante escrita. Arquivos com
+menos de 1 hora sao pulados (periodo de graca para escritas em andamento);
+orfaos mais antigos sao deletados.</li>
+<li><strong>Refcounts vazados</strong> — linhas em <code>cas_objects</code> com refcount zero que nao
+foram limpas (ex: se o processo morreu entre decrementar e deletar). Essas
+linhas sao removidas.</li>
+<li><strong>Idempotente</strong> — executar sweep duas vezes produz o mesmo resultado.</li>
+</ol>
+<p>O sweep e conectado ao loop de reparo existente em <code>tesseras-replication</code>, entao
+roda automaticamente a cada 24 horas junto com as verificacoes de saude dos
+fragmentos.</p>
+<p><strong>Migracao do layout antigo</strong> (<code>tesseras-storage/src/migration.rs</code>) — Uma
+estrategia de migracao copy-first que move dados do layout antigo baseado em
+diretorios (<code>blobs/&lt;tessera&gt;/&lt;memoria&gt;/&lt;arquivo&gt;</code> e
+<code>fragments/&lt;tessera&gt;/&lt;indice&gt;.shard</code>) para o CAS. A migracao:</p>
+<ol>
+<li>Verifica a versao de armazenamento em <code>storage_meta</code> (versao 1 = layout
+antigo, versao 2 = CAS)</li>
+<li>Percorre os diretorios antigos <code>blobs/</code> e <code>fragments/</code></li>
+<li>Computa hashes BLAKE3 e insere no CAS via <code>put()</code> — duplicatas sao
+automaticamente deduplicadas</li>
+<li>Cria entradas correspondentes em <code>blob_refs</code> / <code>fragment_refs</code></li>
+<li>Remove diretorios antigos somente apos todos os dados estarem seguros no CAS</li>
+<li>Atualiza a versao de armazenamento para 2</li>
+</ol>
+<p>A migracao roda na inicializacao do daemon, e idempotente (segura para
+re-executar) e reporta estatisticas: arquivos migrados, duplicatas encontradas,
+bytes economizados.</p>
+<p><strong>Metricas Prometheus</strong> (<code>tesseras-storage/src/metrics.rs</code>) — Dez novas metricas
+para observabilidade:</p>
+<table><thead><tr><th>Metrica</th><th>Descricao</th></tr></thead><tbody>
+<tr><td><code>cas_objects_total</code></td><td>Total de objetos unicos no CAS</td></tr>
+<tr><td><code>cas_bytes_total</code></td><td>Total de bytes armazenados</td></tr>
+<tr><td><code>cas_dedup_hits_total</code></td><td>Numero de escritas que encontraram um objeto existente</td></tr>
+<tr><td><code>cas_bytes_saved_total</code></td><td>Bytes economizados por deduplicacao</td></tr>
+<tr><td><code>cas_gc_refcount_deletions_total</code></td><td>Objetos deletados quando refcount chegou a zero</td></tr>
+<tr><td><code>cas_gc_sweep_orphans_cleaned_total</code></td><td>Arquivos orfaos removidos pelo sweep</td></tr>
+<tr><td><code>cas_gc_sweep_leaked_refs_cleaned_total</code></td><td>Linhas de refcount vazadas limpas</td></tr>
+<tr><td><code>cas_gc_sweep_skipped_young_total</code></td><td>Orfaos jovens pulados (periodo de graca)</td></tr>
+<tr><td><code>cas_gc_sweep_duration_seconds</code></td><td>Tempo gasto no sweep GC</td></tr>
+</tbody></table>
+<p><strong>Testes baseados em propriedades</strong> — Dois testes proptest verificam invariantes
+do CAS sob entradas aleatorias:</p>
+<ul>
+<li><code>refcount_matches_actual_refs</code> — apos N operacoes aleatorias de put/release, o
+refcount sempre corresponde ao numero real de referencias pendentes</li>
+<li><code>cas_path_is_deterministic</code> — o mesmo hash sempre produz o mesmo caminho no
+sistema de arquivos</li>
+</ul>
+<p><strong>Atualizacao de testes de integracao</strong> — Todos os testes de integracao em
+<code>tesseras-core</code>, <code>tesseras-replication</code>, <code>tesseras-embedded</code> e <code>tesseras-cli</code>
+atualizados para os novos construtores com CAS. Testes de deteccao de
+adulteracao atualizados para funcionar com o layout de diretorio CAS.</p>
+<p>347 testes passam em todo o workspace. Clippy limpo com <code>-D warnings</code>.</p>
+<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2>
+<ul>
+<li><strong>BLAKE3 como chave CAS</strong>: o hash de conteudo que ja computamos para
+verificacao de integridade serve tambem como chave de deduplicacao. Nenhuma
+etapa adicional de hashing — o hash computado durante <code>create</code> ou <code>replicate</code>
+e reutilizado como endereco CAS.</li>
+<li><strong>Refcount SQLite ao inves de reflinks do sistema de arquivos</strong>: consideramos
+usar copy-on-write no nivel do sistema de arquivos (reflinks em btrfs/XFS),
+mas isso amarraria o Tesseras a sistemas de arquivos especificos. Refcounting
+em SQLite funciona em qualquer sistema de arquivos, incluindo FAT32 em
+pendrives baratos e ext4 em Raspberry Pis.</li>
+<li><strong>Diretorios de prefixo hexadecimal de dois niveis</strong>: armazenar todos os
+objetos CAS em um diretorio plano desaceleraria sistemas de arquivos com
+milhoes de entradas. A divisao <code>&lt;prefixo 2 chars&gt;/</code> limita qualquer diretorio
+individual a ~65k entradas antes de um segundo nivel ser necessario. Isso
+segue a abordagem usada pelo object store do Git.</li>
+<li><strong>Periodo de graca para arquivos orfaos</strong>: o sweep GC pula arquivos com menos
+de 1 hora para evitar deletar objetos sendo escritos por uma operacao
+concorrente. Esta e uma escolha pragmatica — troca uma pequena janela de
+potenciais orfaos por seguranca contra crashes sem exigir fsync ou commit de
+duas fases.</li>
+<li><strong>Migracao copy-first</strong>: a migracao copia dados para o CAS antes de remover
+diretorios antigos. Se o processo for interrompido, os dados antigos
+permanecem intactos e a migracao pode ser re-executada. Isso e mais lento que
+mover arquivos mas garante zero perda de dados.</li>
+<li><strong>Sweep no loop de reparo</strong>: ao inves de adicionar um timer separado de GC, o
+sweep CAS aproveita o loop de reparo existente de 24 horas. Isso mantem o
+daemon simples — um unico ciclo de manutencao em segundo plano cuida tanto da
+saude dos fragmentos quanto da limpeza de armazenamento.</li>
+</ul>
+<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2>
+<ul>
+<li><strong>Fase 4 continuacao</strong> — auditorias de seguranca, empacotamento para OS
+(Alpine, Arch, Debian, OpenBSD, FreeBSD)</li>
+<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por
+era/localizacao/tema/idioma, curadoria institucional, integracao genealogica
+(FamilySearch, Ancestry), exportacao para midia fisica (M-DISC, microfilme,
+papel livre de acido com QR), contexto assistido por IA</li>
+</ul>
+<p>A deduplicacao de armazenamento completa a historia de eficiencia de
+armazenamento do Tesseras. Um no que armazena fragmentos para milhares de
+usuarios — comum para nos institucionais e nos completos sempre ligados — agora
+paga o custo de disco apenas por dados unicos. Combinado com codificacao de
+apagamento Reed-Solomon (que ja minimiza redundancia no nivel da rede), o
+sistema alcanca armazenamento eficiente tanto nas camadas local quanto
+distribuida.</p>
+
+</article>
+
+ </main>
+
+ <footer>
+ <p>&copy; 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p>
+ </footer>
+</body>
+</html>
diff --git a/pt-br/news/phase4-storage-deduplication/index.html.gz b/pt-br/news/phase4-storage-deduplication/index.html.gz
new file mode 100644
index 0000000..5e8ad15
--- /dev/null
+++ b/pt-br/news/phase4-storage-deduplication/index.html.gz
Binary files differ