Enabling native persistence

We turn on Ignite's native persistence to store data on disk. Ignite keeps a subset of the data in memory and a superset on disk. If a cache has N entries and it is configured to keep only X objects in memory (X < N), then X-N objects are stored on disk.

The following are the advantages of native persistence:

  • You can run distributed SQL queries over the full dataset, which spans both memory and disk.
  • You don't have to worry about the size of the data and indexes in RAM. Ignite allows you to keep only the frequently used dataset in memory; the rest of the data can be stored on disk.
  • When the entire cluster goes down and you restart it, the third-party persistence needs to preload the data and warm up the memory before it becomes operational. The native persistence cluster becomes fully operational once all the nodes are interconnected with each other.
  • The native persistence keeps data and indexes in memory and on disk. But the format of in-memory data and disk data is the same. Therefore, while moving data from RAM to disk, Ignite doesn't worry about transforming data from one format to another. On the other hand, the third-party persistence needs to transform /deserialize objects from one format to another, which is an overhead.

In the following section, we'll create a cache, enable native persistence, populate the cache, restart the node, and verify the behavior. The following are the requisite steps:

  1. You need to start two Ignite server nodes with the persistenceEnabled flag set to true. The examples folder contains the persistence configuration file. Open the example-persistent-store.xml file and modify the following DataStorageConfiguration to enable persistence:
      <!-- Enabling Apache Ignite Persistent Store. -->
<property name="dataStorageConfiguration">
<bean
class="org.apache.ignite.configuration.DataStorageConfiguration">
<property name="defaultDataRegionConfiguration">
<bean
class="org.apache.ignite.configuration.DataRegionConfiguration">
<property name="persistenceEnabled" value="true"/>
</bean>
</property>
</bean>
</property>

Launch two command prompts and run ignite examples/config/persistentstore/example-persistent-store.xml:

  1. Add a new Java class, NativePersistenceTest, to our service grid project to create a cache and populate it with a custom MyPojo class. MyPojo is a simple POJO class:
     class MyPojo implements Serializable {
private static final long serialVersionUID = 1L;
private String message;
public MyPojo(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
@Override
public String toString() {
return "MyPojo [message=" + message + "]";
}
}
  1. NativePersistenceTest creates a cache called NativePersistence and its configuration, activates the cluster as the cluster's persistence property is changed, and populates the cache with 100_000 MyPojo entries:
      public class NativePersistenceTest {
public static void main(String[] args) {
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setClientMode(true);

CacheConfiguration<String, MyPojo> config = new
CacheConfiguration<>();
config.setName("NativePersistence");
config.setIndexedTypes(String.class, MyPojo.class);
cfg.setCacheConfiguration(config);

Ignite ignite = Ignition.start(cfg);
ignite.cluster().active(true);
IgniteCache<String, MyPojo> myPojoCache =
ignite.getOrCreateCache(config);
IntStream.range(1, 100000).forEach(
i -> {
System.out.println(String.format("putting %s in
cache", i));
myPojoCache.put(String.valueOf(i), new
MyPojo(String.valueOf(i)));
}
);
}
}
  1. Run the program. It will put the objects in cache and the server nodes start persisting the elements. Go to the <<IGNITE_HOME>>/work/db folder. You will see the following two sub-folders: starting with node00- and node01-, representing the two server nodes we started, and a wal folder for the logs:

  1. Each node folder contains a unique directory for every cache deployed on that node. If we deploy two caches, it will contain two directories. Open both node directories. They contain the cache-NativePersistence folder for our NativePersistence cache: 

  1. Open the cache-NativePersistence folder. You will see many part-n.bin (part-0, part-2, and so on) files and an index.bin file. A part-n.bin file is created for every partition that this node is either a primary or backup of. We have two nodes, so the cache entries were partitioned into two sets: node00 contains part-0, part-2, and so on, and node01 contains part-1, part-4, and so on.index.bin keeps track of the cache indexes:

Our NativePersistence cache data is persisted on disk. Now restart the nodes. You should still be able to fetch the data that we stored in the cache. The following code queries the NativePersistence cache to get the values:

  1. Create a NativePersistenceAccessTest class, add the following code snippet to activate the cluster, and fetch 100_000 entries from the cache:
      public class NativePersistenceAccessTest {
public static void main(String[] args) {
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setClientMode(true);
Ignite ignite = Ignition.start(cfg);
ignite.cluster().active(true);
IgniteCache<String, MyPojo> myPojoCache =
ignite.getOrCreateCache("NativePersistence");
IntStream.range(1, 100000).forEach(i -> {
System.out.println(myPojoCache.get(String.valueOf(i)));
});
}
}
  1. Restart the server nodes and run the program. It will print the cache entries:

One of the advantage of native persistence is that the cluster becomes fully operational once all the nodes are connected with each other.

What if one of the cluster nodes doesn't come up? 

The following process examines the cluster restart and node failure behavior:

  1. Kill one server node and restart the program.
  2. It will throw the following exception: org.apache.ignite.cache.CacheServerNotFoundException: Failed to map keys for cache (all partition nodes left the grid):

  1. Since we killed the node that contained the partition for key =5, it raised an exception.

It looks like native persistence has a serious problem: if a node fails to start, then the application will lose data!

The problem lies within our cache configuration, not in native persistence. We need to reconfigure our cache to keep a backup!

The following process examines this behavior:

  1. Stop the server nodes.
  2. Delete the db folder from the <<IGNITE_INSTALLATION>>/work directory.
  3. Start two server nodes using the ignite examples/config/persistentstore/example-persistent-store.xml command.
  4. Modify our NativePersistenceTest's cache configuration to create a backup:
       config.setName("NativePersistence");
config.setBackups(1);
config.setIndexedTypes(String.class, MyPojo.class);
  1. Run the NativePersistenceTest program again.
  2. Now kill all server nodes.
  1. Start only one node using the ignite examples/config/persistentstore/example-persistent-store.xml command.
  2. Run NativePersistenceAccessTest again. It should not fail, and it should print the following message:

We'll learn about Write Ahead Log (WAL) and checkpointing in the performance tuning section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.210.71