Integrating Memcached and Redis access using flea-frame-cache

Keywords: Redis xml Spring socket

Integrate Memcached and Redis access

Reference resources

Integrating Memcached and Redis access source code used by flea-frame-cache

rely on

No more, see my blog entry below:

Memcached access used by flea-frame-cache

Redis access used by flea-frame-cache

Use Instructions

After the last two posts, Memcached and Redis believe that many friends will be able to successfully access system applications.As the complexity of applications increases, the application scenarios of caching become more and more complex. Individual docking of a caching system can no longer meet the requirements of business development.This paper focuses on integrating multiple sets of cache access: one cache corresponds to one cache-data, one cache-data corresponds to one cache-group, multiple cache-server s associate one cache-group, and one cache-group corresponds to a specific cache access implementation.(Memcached and Redis are currently supported).Now listen to me slowly:

1. Flea cache profile flea-cache-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<flea-cache-config>

    <!-- Flea Cache Configuration Itemset -->
    <cache-items key="FleaCacheBuilder" desc="Flea Cache Builder Implementation">
        <cache-item key="MemCached" desc="MemCached Of Flea Cache Builder Implementation">com.huazie.frame.cache.memcached.MemCachedFleaCacheBuilder</cache-item>
        <cache-item key="Redis" desc="Redis Of Flea Cache Builder Implementation">com.huazie.frame.cache.redis.RedisFleaCacheBuilder</cache-item>
    </cache-items>

    <!-- Redis Cache parameter set -->
    <cache-params key="Redis" desc="Redis Cache configuration data">
        <cache-param key="connectionTimeout" desc="Redis Client socket Connection timeout">2000</cache-param>
        <cache-param key="soTimeout" desc="Redis Client socket Read-Write Timeout">2000</cache-param>
        <cache-param key="hashingAlg" desc="Redis Distributed hash algorithm(1:MURMUR_HASH,2:MD5)">1</cache-param>
        <cache-param key="pool.maxTotal" desc="Redis Client Jedis Maximum Connections in Connection Pool">8</cache-param>
        <cache-param key="pool.maxIdle" desc="Redis Client Jedis Maximum number of idle connections in connection pool">8</cache-param>
        <cache-param key="pool.minIdle" desc="Redis Client Jedis Connection pool minimum number of idle connections">0</cache-param>
        <cache-param key="pool.maxWaitMillis" desc="Redis Client Jedis Maximum number of milliseconds to wait for a connection to be acquired by the connection pool">2000</cache-param>
    </cache-params>

    <!-- MemCached Cache parameter set -->
    <cache-params key="MemCached" desc="MemCached Cache configuration data">
        <cache-param key="initConn" desc="Number of connections made to each server at initialization">20</cache-param>
        <cache-param key="minConn" desc="Minimum number of connections per server">20</cache-param>
        <cache-param key="maxConn" desc="Maximum number of connections per server">500</cache-param>
        <cache-param key="maintSleep" desc="Self-checking thread cycles for work, each time it hibernates">60000</cache-param>
        <cache-param key="nagle" desc="Socket Parameter, if true Send out immediately without buffering while writing data">true</cache-param>
        <cache-param key="socketTO" desc="Socket Timeout to block reading data">3000</cache-param>
        <cache-param key="socketConnectTO" desc="Socket Connection timeout">3000</cache-param>
        <!--
            0 - native String.hashCode();
            1 - original compatibility
            2 - new CRC32 based
            3 - MD5 Based
        -->
        <cache-param key="hashingAlg" desc="MemCached Distributed hash algorithm">3</cache-param>
    </cache-params>

    <!-- Flea Cached Dataset -->
    <cache-datas>
        <cache-data type="auth" desc="Flea Configuration of the group in which permission cached data resides">authGroup</cache-data>
        <cache-data type="jersey" desc="Flea Jersey Configuration of the group in which the cached data resides">configGroup</cache-data>
        <cache-data type="fleafs" desc="FleaFs Configuration Data in Group Configuration">configGroup</cache-data>
    </cache-datas>

    <!-- Flea Cache Group Set -->
    <cache-groups>
        <cache-group group="authGroup" desc="Flea Permission Data Cache Group">MemCached</cache-group>
        <cache-group group="configGroup" desc="Flea Configure Data Cache Group">Redis</cache-group>
    </cache-groups>

    <!-- Flea Cache Server Set -->
    <cache-servers>
        <cache-server group="authGroup" weight="1" desc="MemCached Cache Server Configuration">127.0.0.1:31113</cache-server>
        <cache-server group="authGroup" weight="1" desc="MemCached Cache Server Configuration">127.0.0.1:31114</cache-server>

        <cache-server group="configGroup" password="huazie123" weight="1" desc="Redis Cache Server Configuration">127.0.0.1:10001</cache-server>
        <cache-server group="configGroup" password="huazie123" weight="1" desc="Redis Cache Server Configuration">127.0.0.1:10002</cache-server>
        <cache-server group="configGroup" password="huazie123" weight="1" desc="Redis Cache Server Configuration">127.0.0.1:10003</cache-server>
    </cache-servers>

</flea-cache-config>

2. Flea cache definition file flea-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<flea-cache>
	<!-- Cache Definition -->
    <caches>
        <!-- 
            key : Cache Primary Key, Cache Name 
            type : Cache type
            expiry : Cache expiration time (units: s),This field can be configured (default persistent)
            desc : Cache description
         -->
        <cache key="fleaparadetail" type="fleafs" expiry="86400" desc="Flea Configure Data Cache" />
        
        <cache key="fleajerseyi18nerrormapping" type="jersey" desc="Flea Jersey International Code and Error Code Mapping Cache" />
        <cache key="fleajerseyresservice" type="jersey" desc="Flea Jersey Resource Service Cache" />
        <cache key="fleajerseyresclient" type="jersey" desc="Flea Jersey Resource Client Cache" />
        <cache key="fleajerseyresource" type="jersey" desc="Flea Jersey Resource Cache" />
    </caches>

</flea-cache>

3. Define CoreFleaCache, the core Flea cache class

The class also inherits the abstract Flea cache AbstractFleaCache, which implements the abstract method of its definition; the internal definition member variable fleaCache is used to specify a specific Flea cache implementation (this specific implementation can refer to the previous Memcached and Redis access), which implements the three methods getNativeValue, putNativeValue, deleteNativeValue FleaCache implements read cache, write cache and delete cache by specific Flea cache. From the construction method, fleaCache is obtained from FleaCacheFactory.getFleaCache(name).

/**
 * <p> Core Flea Cache Class </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class CoreFleaCache extends AbstractFleaCache {

    private static final Logger LOGGER = LoggerFactory.getLogger(CoreFleaCache.class);

    private AbstractFleaCache fleaCache; // Specify Flea Cache Implementation

    /**
     * <p> Initialize core Flea cache class </p>with parametric construction method
     *
     * @param name Cache Primary Key
     * @since 1.0.0
     */
    public CoreFleaCache(String name) {
        super(name, CacheConfigManager.getExpiry(name));
        // Gets the specified Flea cache object based on the cache primary key name
        fleaCache = FleaCacheFactory.getFleaCache(name);
        // Takes the cache type of the specified Flea cache
        cache = fleaCache.getCache();
    }

    @Override
    public Object getNativeValue(String key) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("CoreFleaCache##getNativeValue(String) KEY = {}", key);
        }
        return fleaCache.getNativeValue(key);
    }

    @Override
    public void putNativeValue(String key, Object value, long expiry) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("CoreFleaCache##putNativeValue(String, Object, long) KEY = {}", key);
            LOGGER.debug("CoreFleaCache##putNativeValue(String, Object, long) VALUE = {}", value);
            LOGGER.debug("CoreFleaCache##putNativeValue(String, Object, long) EXPIRY = {}s", expiry);
        }
        fleaCache.putNativeValue(key, value, expiry);
    }

    @Override
    public void deleteNativeValue(String key) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("CoreFleaCache##deleteNativeValue(String) KEY = {}", key);
        }
        fleaCache.deleteNativeValue(key);
    }
}

4. Define Flea CacheFactory class

Flea caches created by this class based on the cache name (that is, the cache primary key) are stored in ConcurrentMap < String, AbstractFleaCache >.The newCache method mainly finds the cache based on the cache name, then finds the cache-data, then finds the cache group cache-group, and finally finds the cache configuration item cache-item based on the cache system to which the cache group belongs, to get the builder implementation of the corresponding Flea cache, see the flea-cache-config.xml configuration.

/**
 * <p> Flea Cache Factory Class </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class FleaCacheFactory {

    private static final ConcurrentMap<String, AbstractFleaCache> fleaCacheMap = new ConcurrentHashMap<String, AbstractFleaCache>();

    /**
     * <p> Gets the specified Flea cache object from the cache primary key name </p>
     *
     * @param name Cache Primary Key (corresponding to flea-cache.xml {@code <cache key= "Cache Primary Key"></cache>})
     * @return Flea Cache Object
     * @since 1.0.0
     */
    public static AbstractFleaCache getFleaCache(String name) {
        if (!fleaCacheMap.containsKey(name)) {
            synchronized (fleaCacheMap) {
                if (!fleaCacheMap.containsKey(name)) {
                    fleaCacheMap.put(name, newFleaCache(name));
                }
            }
        }
        return fleaCacheMap.get(name);
    }

    /**
     * <p> Create a Flea cache object from the cache primary key name </p>
     *
     * @param name Cache Primary Key (corresponding to flea-cache.xml {@code <cache key= "Cache Primary Key"></cache>})
     * @return Flea Cache Object
     * @since 1.0.0
     */
    private static AbstractFleaCache newFleaCache(String name) {
        // Get Flea Cache Configuration Information
        Cache cache = CacheConfigManager.getCache(name);
        if (ObjectUtils.isEmpty(cache)) {
            throw new RuntimeException("Unable to initialize Flea Cache, please check flea-cache.xml Configuration [<cache key=" + name + " >]");
        }
        // Get Flea Cache Attribution Data Configuration Information
        CacheData cacheData = CacheConfigManager.getCacheData(cache.getType());
        if (ObjectUtils.isEmpty(cacheData)) {
            throw new RuntimeException("Unable to initialize Flea Cache, please check flea-cache-config.xml Configuration [<cache-data type=" + cache.getType() + " >]");
        }
        // Get Flea Cache Group
        CacheGroup cacheGroup = CacheConfigManager.getCacheGroup(cacheData.getGroup());
        if (ObjectUtils.isEmpty(cacheGroup)) {
            throw new RuntimeException("Unable to initialize Flea Cache, please check flea-cache-config.xml Configuration [<cache-group group=" + cacheData.getGroup() + " >]");
        }
        // Get Cache System Name
        String cacheSystem = cacheGroup.getCache();
        // Get Flea Cache Parameters
        CacheParams cacheParams = CacheConfigManager.getCacheParams(cacheSystem);
        if (ObjectUtils.isEmpty(cacheParams)) {
            throw new RuntimeException("Unable to initialize Flea Cache, please check flea-cache-config.xml Configuration [<cache-params key=" + cacheGroup.getCache() + " >]");
        }
        // Get Flea Cache Server
        List<CacheServer> cacheServerList = CacheConfigManager.getCacheServer(cacheGroup.getGroup());
        if (CollectionUtils.isEmpty(cacheServerList)) {
            throw new RuntimeException("Unable to initialize Flea Cache, please check flea-cache-config.xml Configuration [<cache-server group=" + cacheGroup.getGroup() + " >]");
        }
        // Gets the Flea cache builder corresponding to the specified cache system name
        CacheItem cacheItem = CacheConfigManager.getCacheItem(CacheConstants.FleaCacheConfigConstants.FLEA_CACHE_BUILDER, cacheSystem);
        if (ObjectUtils.isEmpty(cacheItem)) {
            throw new RuntimeException("Unable to initialize Flea Cache, please check flea-cache-config.xml Configuration [<cache-item key=" + cacheSystem + " >]");
        }
        // Flea Cache Builder
        String builder = cacheItem.getValue();
        if (ObjectUtils.isEmpty(builder)) {
            throw new RuntimeException("Unable to initialize Flea Cache, please check flea-cache-config.xml Configuration [<cache-item key=" + cacheSystem + " ></cache-item>]Configuration item value cannot be empty");
        }
        AbstractFleaCache fleaCache;
        try {
            IFleaCacheBuilder fleaCacheBuilder = (IFleaCacheBuilder) ReflectUtils.newInstance(builder);
            fleaCache = fleaCacheBuilder.build(name, cacheServerList, cacheParams);
        } catch (Exception e) {
            throw new RuntimeException("structure Flea Cache exception:\n" + e);
        }
        return fleaCache;
    }

}

5. Define the Flea cache builder interface class IFleaCacheBuilder

/**
 * <p> Flea Cache Builder Interface Class </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public interface IFleaCacheBuilder {

    /**
     * <p> Build Flea Cache Object </p>
     *
     * @param name            Cache Primary Key
     * @param cacheServerList Cache Server Set
     * @param cacheParams     Cache parameter set
     * @return Flea Cache Object
     * @since 1.0.0
     */
    AbstractFleaCache build(String name, List<CacheServer> cacheServerList, CacheParams cacheParams);

}

6. Define Memcached Flea cache builder MemCached FleaCacheBuilder

This class implements IFleaCacheBuilder, which is used to build a Memcached-based Flea cache by creating a MemCached FleaCache.

/**
 * <p> MemCached Flea cache builder implementation for </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class MemCachedFleaCacheBuilder implements IFleaCacheBuilder {

    private static final Logger LOGGER = LoggerFactory.getLogger(MemCachedFleaCacheBuilder.class);

    @Override
    public AbstractFleaCache build(String name, List<CacheServer> cacheServerList, CacheParams cacheParams) {

        if (CollectionUtils.isEmpty(cacheServerList)) {
            return null;
        }
        // Get Failure Time
        long expiry = CacheConfigManager.getExpiry(name);
        // Get the group name of the MemCached server
        String group = cacheServerList.get(0).getGroup();
        // Get the MemCached client class by group name
        MemCachedClient memCachedClient = new MemCachedClient(group);
        // Get the MemCachedPool and initialize the connection pool
        MemCachedPool memCachedPool = MemCachedPool.getInstance(group);
        memCachedPool.initialize(cacheServerList, cacheParams);
        // Create a MemCached Flea cache class
        AbstractFleaCache fleaCache = new MemCachedFleaCache(name, expiry, memCachedClient);

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("MemCachedFleaCacheBuilder#build(String, List<CacheServer>, CacheParams) Pool Name = {}", memCachedPool.getPoolName());
            LOGGER.debug("MemCachedFleaCacheBuilder#build(String, List<CacheServer>, CacheParams) Pool = {}", memCachedPool.getSockIOPool());
        }

        return fleaCache;
    }
}

7. Define RedisFleaCacheBuilder, the Redis Flea cache builder

This class implements IFleaCacheBuilder, which is used to build a Redis-based Flea cache by creating a RedisFleaCache.

/**
 * <p> Redis Flea cache builder implementation for </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class RedisFleaCacheBuilder implements IFleaCacheBuilder {

    private static final Logger LOGGER = LoggerFactory.getLogger(RedisFleaCacheBuilder.class);

    @Override
    public AbstractFleaCache build(String name, List<CacheServer> cacheServerList, CacheParams cacheParams) {
        if (CollectionUtils.isEmpty(cacheServerList)) {
            return null;
        }
        // Get Failure Time
        long expiry = CacheConfigManager.getExpiry(name);
        // Get Cache Group Name
        String group = cacheServerList.get(0).getGroup();
        // Initialize connection pool
        RedisPool.getInstance(group).initialize(cacheServerList, cacheParams);
        // Get Redis Client Proxy Class
        RedisClient redisClient = RedisClientProxy.getProxyInstance(group);
        // Create a Redis Flea cache
        AbstractFleaCache fleaCache = new RedisFleaCache(name, expiry, redisClient);

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("RedisFleaCacheBuilder#build(String, List<CacheServer>, CacheParams) Pool Name = {}", RedisPool.getInstance(group).getPoolName());
            LOGGER.debug("RedisFleaCacheBuilder#build(String, List<CacheServer>, CacheParams) Pool = {}", RedisPool.getInstance(group).getJedisPool());
        }

        return fleaCache;
    }
}

8. Define Core FleaCache Manager, the core Flea cache management class

Core Flea Cache is ready for use after the above steps; it inherits AbstractFleaCache Manager and implements the newCache method to create a core Flea cache.

/**
 * <p> Core Flea Cache Management Class </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class CoreFleaCacheManager extends AbstractFleaCacheManager {

    @Override
    protected AbstractFleaCache newCache(String name, long expiry) {
        return new CoreFleaCache(name);
    }
}

9. Cache self-testing

    @Test
    public void testCoreFleaCacheManager() {
        try {
            AbstractFleaCacheManager manager = new CoreFleaCacheManager();
            AbstractFleaCache cache = manager.getCache("fleaparadetail");
            LOGGER.debug("Cache={}", cache);
            //##### 1. Simple string
//            cache.put("menu1", "huazie");
//            cache.put("menu2", "helloworld");
//            cache.get("menu1");
//            cache.delete("menu2");
            cache.getCacheKey();
            LOGGER.debug(cache.getCacheName() + ">>>" + cache.getCacheDesc());
        } catch (Exception e) {
            LOGGER.error("Exception:", e);
        }
    }

After the above introduction, the core Flea cache related content is basically explained.On the basis of unchanged existing business code, related cache caches can migrate seamlessly between caches by modifying the type of cache data they belong to.

Advanced Practice

1. Define Core Spring Cache

The class also inherits the abstract Spring cache AbstractSpring Cache, which is used to dock Spring; from the construction method, it initializes using the core Flea cache class CoreFleaCache.

/**
 * <p> Core Spring Cache Class </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class CoreSpringCache extends AbstractSpringCache {

    /**
     * <p> Construction method with parameters </p>
     *
     * @param name      Cache Primary Key
     * @param fleaCache Flea Cache Specific implementation
     * @since 1.0.0
     */
    public CoreSpringCache(String name, IFleaCache fleaCache) {
        super(name, fleaCache);
    }

    /**
     * <p> Construction method with parameters </p>
     *
     * @param name Cache Primary Key
     * @since 1.0.0
     */
    public CoreSpringCache(String name) {
        super(name, new CoreFleaCache(name));
    }
}

2. Define Core Spring Cache Manager, a core Spring cache management class

This class inherits the abstract Spring cache management class AbstractSpring Cache Manager, which is used to dock Spring; it basically implements Core Flea Cache Manager, the only difference being the implementation of newCache, which is a new core Spring cache CoreSpring Cache.

/**
 * <p> Core Spring Cache Management Class </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class CoreSpringCacheManager extends AbstractSpringCacheManager {

    @Override
    protected AbstractSpringCache newCache(String name, long expiry) {
        return new CoreSpringCache(name);
    }
}

3. Spring Configuration

<!-- Configuration Core Flea Cache Management Class RedisSpringCacheManager -->
<bean id="coreSpringCacheManager" class="com.huazie.frame.cache.core.CoreSpringCacheManager" />

<!-- Open Cache -->
<cache:annotation-driven cache-manager="coreSpringCacheManager" proxy-target-class="true"/>

4. Cache self-testing

    private ApplicationContext applicationContext;

    @Before
    public void init() {
        applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        LOGGER.debug("ApplicationContext={}", applicationContext);
    }
    
    @Test
    public void testCoreSpringCache() {
        try {
            AbstractSpringCacheManager manager = (CoreSpringCacheManager) applicationContext.getBean("coreSpringCacheManager");
            LOGGER.debug("CoreSpringCacheManager={}", manager);

            AbstractSpringCache cache = manager.getCache("fleaparadetail");
            LOGGER.debug("Cache={}", cache);

            //##### 1. Simple string
//			cache.put("menu1", "huazie");
//            cache.get("menu1");
//            cache.get("menu1", String.class);

            //##### 2. Simple objects (if serializable)
//			String user = new String("huazie");
//			cache.put("user", user);
//			LOGGER.debug(cache.get("user", String.class));
//            cache.get("FLEA_RES_STATE");
            cache.clear();

            //##### 3. Listplug object
//			List<String> userList = new ArrayList<String>();
//			userList.add("huazie");
//			userList.add("lgh");
//			cache.put("user_list", userList);

//			LOGGER.debug(cache.get("user_list",userList.getClass()).toString());

        } catch (Exception e) {
            LOGGER.error("Exception:", e);
        }
    }

5. Business Logic Layer Access Cache Management

@Cacheable, value is the cache name, also the cache primary key, key is the specific cache key

@Cacheable(value = "fleaparadetail", key = "#paraType + '_' + #paraCode")
public FleaParaDetail getParaDetail(String paraType, String paraCode) throws Exception {

    List<FleaParaDetail> fleaParaDetails = fleaParaDetailDao.getParaDetail(paraType, paraCode);
    FleaParaDetail fleaParaDetailValue = null;

    if (CollectionUtils.isNotEmpty(fleaParaDetails)) {
        fleaParaDetailValue = fleaParaDetails.get(0);
    }

    return fleaParaDetailValue;
}

So far, the integration of Memcached and Redis access has been completed, and you are confident that you can access the system~

Posted by gooman on Thu, 22 Aug 2019 18:50:58 -0700