Apache Ignite — Cache — Parte 1

Charles Fonseca
3 min readJan 8, 2021

--

Apache Ignite é uma plataforma para computação distribuída desenvolvida pela GridGain, posteriormente doada à Apache Foundation. Esta é uma série de artigos acerca da plataforma Ignite, cujo propõe-se contemplar o funcionamento alto nível, abordando algumas questões internas de implementação.

O Ignite está inserido em diversos contextos: cache, mensageria, streaming, monitoração, eventos, computação distribuída. Todos os módulos serão abordados nesta série. Como subir um cluster e node Ignite está documentado aqui.

Arquitetura de memória

O gerenciamento de memória é um dos diferenciais do Ignite, os dados são mantidos tanto em memória (RAM) e disco.

Caso a instância seja configurada como cache-aside, ou seja, não interaja com nenhuma camada de persistência (JDBC, Spring Data, Micronaut Data), ele utilizada os discos dos nodes como detentor da verdade — source of truth — em caso de inconsistência. Caso contrário, um processo chamado change-data-capture process (CDC) é responsável pela sincronização eventual dos dados no cluster.

Quando alocados em memória, parte é destinada on-heap, ou seja, é mantida em memória destinada à instância Java Virtual Machine (JVM) do próprio Ignite — cujo é uma aplicação Java —, o que pode ser desnecessariamente custoso, visto que ao executar o garbage collector ele analisa todo o heap, o que pode roubar alguns bons ciclos de CPU da aplicação. A outra forma é off-heap, fora da memória destinada ao Java, e gerenciado exclusivamente pelo Ignite. Segue a representação:

Arquitetura de memória Ignite
https://ignite.apache.org/docs/latest/memory-architecture

Cache

Features

  • Estruturas de dados em cache

As interfaces IgniteSet<T> extends Set<T> e IgniteQueue<T> extends BlockingQueue<T> possibilitam criar estruturas de dados completamente distribuídas através dos nós, com backup, e particionamento próprio de maneira transparente ao usuário. Visto que estas estruturas herdam das implementações Java, todas operações nativas da linguagem, estão facilmente disponíveis.

  • Implementação para ambas as operações síncronas e assíncronas

Todas as operações assíncronas implementam a interface IgniteFuture<V> cujo implementação é semelhante ao CompletableFuture do Java, com a possibilidade de inserir função callback, ou encadear operações.

  • Métricas avançadas

A API de cache expõe suas métricas, a quantidade de cache miss, cache hit, put time, get time, tempo de balanceamento de dados, tamanho do heap. Isso torna a experiência de usuário bastante transparente, bem como provê uma visão macro ao desenvolvedor.

  • Serialização/deserialização otimizada
IgniteCache<Integer, Organization> cache = ignite.getOrCreateCache("cacheName");
Organization org = new Organization(
"Microsoft", new Address("1096 Eddy Street, San Francisco, CA"), OrganizationType.PRIVATE));

cache.put(1, org);

// Get cache that will get values as binary objects.
IgniteCache<Integer, BinaryObject> binaryCache = cache.withKeepBinary();
// Get recently created organization as a binary object.
BinaryObject binary = binaryCache.get(1);
// That is how magic happens
String name = binary.field("name");

A implementação BinaryObject.field() nos permite deserializar campos específicos, otimizando a utilização de CPU, visto que apenas o dado será utilizado será processado.

Estruturas de dados distribuídas em cache

  • Queue
IgniteQueue<String> queue = Ignition.ignite().queue("queueName", 0, null);int TIMES = 10;for (int i = 0; i < RETRIES; i++) {
String item = UUID.randomUUID() + "_" + i;
queue.put(item);
println("Queue item has been added: " + item);
}
// IgniteQueue is fully compatible with Java library.
for (String item : queue)
println("Queue item: " + item);
// Take items from queue head.
for (int i = 0; i < TIMES; i++)
println("Queue item has been read from queue head: " + queue.take());
// Take items from queue head once again.
for (int i = 0; i < TIMES; i++)
println("Queue item has been read from queue head: " + queue.poll());
  • Set
IgniteSet<String> set = Ignition.ignite().set("setName", null);for (int i = 0; i < 5; i++) {
String item = UUID.randomUUID() + "_" + i;
set.add(item);
}
for (String item : set)
println("Set item: " + item);
println(set.contains("1"));println("Set size: " + set.size());println("Removed: " + set.remove("0"));

Recomendações

--

--

Charles Fonseca
Charles Fonseca

Written by Charles Fonseca

Passionate software developer, fascinated about arts, music, and Jesus Christ.

No responses yet