Dynamic Construction of J2Cache and Notices

Posted by nickmagus on Sat, 11 May 2019 20:14:40 +0200

All along, we put data dictionary and other information in Redis cache, avoid using it, penetrate the database level, while improving performance. Recently, it was discovered that there were frequent Redis connection timeouts and other anomalies on the line. After tracking, it was found that a new dictionary table with more than 30,000 rows of records had been added. Eventually, unexpected things happened. So you need to increase the cache at the application memory level while keeping it consistent with redis.

Recently, the J2Cache release of sweet potato has been a bit frequent (it is becoming entertainment news), which has attracted my attention successfully. It basically meets this requirement. Because the J2Cache base is based on Ehcache, it loads cached data into memory every time it starts, resulting in slow reboot of local debugging, so it will be extended based on J2Cache (ehcache's disk caching strategy must be ensured). Use normal exit.

Note 1: The configuration parameter name cannot directly use the example in j2cache.properties

Because the project itself uses the configuration center, it can only be integrated based on the dynamic construction of J2Cache. Two BUG s of J2Cache were found at this time. First Directly lead to sweet potatoes overnight Editions (Say no BUG, backhand is a slap, again to apologize for sweet potatoes); Second question Every time the configuration information is not read at startup, and the null pointer exception appears in the code conversion (I think this kind of strong conversion will happen, I suggest that the authorities rewrite it in subsequent versions). After the sweet potato pointer, when using Properties to add configuration dynamically, the prefix of redis. should be removed, so it can only be before J2CacheBuilder.init(config); By removing the prefix from the code, the pit must be bypassed.

See the removePrefix method below for the code.

Note 2: How to set up notifications that do not want to use cluster broadcasting

In addition, if you do not want to use Redis cluster or cluster broadcasting function, you need config.setBroadcast("none"); the parameters inside, in fact, suggest that the official can be changed to enumeration.

The sample code is as follows:

package com.chz.apps.common.j2cache;

import com.chz.apps.common.cache.LocalCache;
import com.chz.apps.common.redisson.RedissionTools;
import net.oschina.j2cache.CacheChannel;
import net.oschina.j2cache.J2CacheBuilder;
import net.oschina.j2cache.J2CacheConfig;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

/**
 * J2Cache Tool class
 * @Author gongstring(gongstring@foxmail.com)
 */
public class J2CacheUtil {

    private static Logger logger = LoggerFactory.getLogger(J2CacheUtil.class);

    private static CacheChannel channel = null;

    /**
     * Initialization Start
     */
    public static void start(){
        Object server = LocalCache.getInstance().get(RedissionTools.REDIS_SERVER_IP);
        Object port = LocalCache.getInstance().get(RedissionTools.REDIS_SERVER_PORT);
        Object timeout = LocalCache.getInstance().get(RedissionTools.REDIS_TIMEOUT);
        Object auth = LocalCache.getInstance().get(RedissionTools.REDIS_AUTH);
        Object database = LocalCache.getInstance().get(RedissionTools.REDIS_DATABASE);
        if(server != null && StringUtils.isNotBlank(server.toString()) && port != null && Integer.parseInt(port.toString()) > 0){
            try {

                Properties l1cacheProperties = new Properties();
                l1cacheProperties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("j2cache/caffeine.properties"));

                Properties l2cacheProperties = new Properties();
                l2cacheProperties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("j2cache/j2cache.properties"));
                //Custom redis configuration connection
                l2cacheProperties.put("redis.hosts",server+":"+port);
                l2cacheProperties.put("redis.timeout",timeout);
                if(auth != null){
                    l2cacheProperties.put("redis.password",auth);
                }

                if(database != null){
                    l2cacheProperties.put("redis.database",database);
                }

                J2CacheConfig config = new J2CacheConfig();
                //No Cluster Notification
                config.setBroadcast("none");
                config.setL1CacheName("caffeine");
                config.setL1CacheProperties(l1cacheProperties);

                config.setL2CacheName("redis");
                config.setL2CacheProperties(removePrefix(l2cacheProperties,"redis."));
                J2CacheBuilder builder = J2CacheBuilder.init(config);
                channel = builder.getChannel();

                logger.info("J2Cache Startup success");
            }catch (Exception e){
                e.printStackTrace();
                logger.error("J2Cache Startup failure:{}",e);
            }
        }else{

            logger.info("J2Cache Start failed, no secondary cache configured Redis Parametric information");
        }


    }

    public static void close(){
        if(channel != null){
            channel.close();
        }
    }

    public static CacheChannel getChannel(){
        return channel;
    }

    private static Properties removePrefix(Properties properties,String prefix){
        if(properties == null)
            return null;

        Properties result = new Properties();
        Iterator<Map.Entry<Object, Object>> it = properties.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Object, Object> entry = it.next();
            if(entry.getKey().toString().startsWith(prefix)){
                result.put(entry.getKey().toString().substring(prefix.length()),entry.getValue());
            }else{
                result.put(entry.getKey(),entry.getValue());
            }
        }
        return result;
    }

    public static void main(String[] args) throws Exception{
        start();

        // Generic code with no specific business significance, just to ensure that the main thread does not exit
        synchronized (J2CacheUtil.class) {
            J2CacheUtil.class.wait();
        }
    }

}


Topics: Redis Database Java Ehcache