[JAVA] Introduction to SpringBoot + In-Memory Data Grid (Data Persistence)

What I did last time

Last time, I used SpringDataGeode to create a SpringBoot application that uses an in-memory data grid, and implemented it so that event processing can be performed when the data is synchronized with the server.

・ Creating an application using SpringDataGeode

Event processing implementation using SpringDataGeode

What to do this time

Persist data registered in the in-memory data grid cache to disk

This time, we will use the function of Spring Data Geode to persist the data registered in the in-memory cache to the local disk, and when the cache built-in application server starts, we will load the persistence file and register the data in the cache. ..

After investigating, it seems that it can be realized just by adding one annotation.

--Added the following annotation to SpringBootApplication.

ServerGeodeApplication.java


package spring.geode.server.geodeServer;

import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
import org.springframework.data.gemfire.config.annotation.EnableDiskStore;
import org.springframework.data.gemfire.config.annotation.EnableDiskStore.DiskDirectory;
import org.springframework.data.gemfire.config.annotation.EnableLocator;
import org.springframework.data.gemfire.config.annotation.EnableManager;
import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;

import spring.geode.geodeCommon.model.User;
import spring.geode.geodeCommon.region.UserRegion;
import spring.geode.server.geodeServer.repository.UserRepository;

@SpringBootApplication
@PeerCacheApplication(name = "SpringGeodeServerApplication", locators = "localhost[40404]")
@EnableGemfireRepositories(basePackageClasses = UserRepository.class)
//Data persistence annotation added this time
@EnableDiskStore(
		name="SimpleDiskStore",
		autoCompact=true,
		diskDirectories = @DiskDirectory(location="/hoge/fuga/SpringGeodeData")
		)
public class GeodeServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(GeodeServerApplication.class, args);
	}

	@Configuration
	@EnableLocator(port = 40404)
	@EnableManager(start = true)
	static class LocatorManagerConfiguration {
	}

	@Configuration
	static class CacheInitializer {
		
		@Bean
	    Region<Integer, User> userRegion(final GemFireCache cache) {
			return new UserRegion().createUserRegion(cache);
	    }
		
		@Bean
	    public ReplicatedRegionFactoryBean<Integer, User> replicatedRegion(GemFireCache cache) {
			return new UserRegion().createUserRegionFactory(cache);
	    }
	}
}

By enabling @EnableDiskStore, the persistence file will be spit out to the absolute path location specified by diskDirectories.

For some reason, the file is not output. .. I tried to find a way to solve it with annotations, but it didn't work. ..

I couldn't help it, so I decided to set it directly to Bean. ..

UserRegion.java


package spring.geode.geodeCommon.region;

import java.io.File;

import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;

import spring.geode.geodeCommon.listener.UserRegionListener;
import spring.geode.geodeCommon.model.User;

/**
 *Manage users{@link Region}Create settings for
 *
 */
public class UserRegion {
	/**
	 * {@link Region}To create
	 * @param cache
	 * @return
	 */
	public Region<Integer, User> createUserRegion(final GemFireCache cache) {
		return cache.<Integer, User>getRegion("Users");
	}

	/**
	 * {@link Region}Make settings for
	 * @param cache
	 * @return
	 */
	public ReplicatedRegionFactoryBean<Integer, User> createUserRegionFactory(GemFireCache cache) {
		ReplicatedRegionFactoryBean<Integer, User> replicatedRegionFactory = new ReplicatedRegionFactoryBean<>();
		UserRegionListener[] listeners = { new UserRegionListener() };

		listeners[0] = new UserRegionListener();
		replicatedRegionFactory.setCacheListeners(listeners);
		replicatedRegionFactory.setClose(false);
		replicatedRegionFactory.setCache(cache);
		replicatedRegionFactory.setRegionName("Users");
		replicatedRegionFactory.setPersistent(true);
		return replicatedRegionFactory;
	}

	/**
	 * {@link Region}Make file persistence settings for
	 * @param cache
	 * @param regionFactory
	 * @return
	 */
	public ReplicatedRegionFactoryBean<Integer, User> configDiskStore(GemFireCache cache,
			ReplicatedRegionFactoryBean<Integer, User> regionFactory) {
		File[] files = { new File("/hoge/fuga/SpringGeode/persistenceFile") };

		cache.createDiskStoreFactory()//
				.setAllowForceCompaction(true)//
				.setAutoCompact(true)//
				.setDiskDirs(files)//
				.create("SimpleDiskStore");

		regionFactory.setDiskStoreName("SimpleDiskStore");

		return regionFactory;
	}
}

The persistence setting is done by the configDiskStore method. A DiskStore is created in Cache, and settings related to various persistence methods and persistence file paths are set.

See here for details

By calling this method in the application and registering the bean, the persistence is finally completed.

GeodeServerApplication.java


package spring.geode.server.geodeServer;

import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
import org.springframework.data.gemfire.config.annotation.EnableLocator;
import org.springframework.data.gemfire.config.annotation.EnableManager;
import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;

import spring.geode.geodeCommon.model.User;
import spring.geode.geodeCommon.region.UserRegion;
import spring.geode.server.geodeServer.repository.UserRepository;

@SpringBootApplication
@PeerCacheApplication(name = "SpringGeodeServerApplication", locators = "localhost[40404]")
@EnableGemfireRepositories(basePackageClasses = UserRepository.class)
public class GeodeServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(GeodeServerApplication.class, args);
	}

	@Configuration
	@EnableLocator(port = 40404)
	@EnableManager(start = true)
	static class LocatorManagerConfiguration {
	}

	@Configuration
	static class CacheInitializer {

		@Bean
		Region<Integer, User> userRegion(final GemFireCache cache) {
			return new UserRegion().createUserRegion(cache);
		}

		@Bean
		public ReplicatedRegionFactoryBean<Integer, User> replicatedRegion(GemFireCache cache) {
			UserRegion region = new UserRegion();
			return region.configDiskStore(cache, region.createUserRegionFactory(cache));
		}
	}
}

Now you can set the persistence for each Region, and when you start the app, you can load the data from the file set in DiskStore and register it in the cache.

I wanted to implement it quickly with annotations, but I regret that it didn't work. .. Shouldn't I customize the ReplicatedRegionFactoryBean by myself? ..

Anyway, it's good because it can be made permanent.

It would be nice if RDB could be set as a persistence target, but I couldn't get the information that SpringDataGeode would provide such a function, so I used the file persistence function once to make it persistent. Saw.

Recommended Posts

Introduction to SpringBoot + In-Memory Data Grid (Data Persistence)
Introduction to SpringBoot + In-Memory Data Grid (Event Handling)
An introduction to Spring Boot + in-memory data grid
Introduction to Ruby 2
Introduction to SWING
Introduction to web3j
Introduction to Micronaut 1 ~ Introduction ~
[Java] Introduction to Java
Introduction to migration
Introduction to java
Introduction to Doma
Introduction to RSpec 4. Create test data with Factory Bot
Introduction to JAR files
Introduction to Ratpack (8)-Session
Introduction to RSpec 1. Test, RSpec
Introduction to bit operation
Introduction to Ratpack (6) --Promise
Introduction to Ratpack (9) --Thymeleaf
Introduction to PlayFramework 2.7 ① Overview
Introduction to Android Layout
Introduction to design patterns (introduction)
Introduction to Practical Programming
Introduction to javadoc command
Introduction to jar command
Introduction to Ratpack (2)-Architecture
Introduction to lambda expression
Introduction to java command
Introduction to RSpec 2. RSpec setup
Introduction to Keycloak development
Introduction to javac command