All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.base4j.cache.broadcast.RedisBroadcastChannel Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
package com.base4j.cache.broadcast;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.base4j.cache.CacheBroadcastChannel;
import com.base4j.cache.CacheException;
import com.base4j.cache.CacheExpiredListener;
import com.base4j.cache.Base4jCacheFactory;
import com.base4j.cache.store.SuperCacheProvider;
import com.base4j.cache.utils.CacheCustoms;
import redis.clients.jedis.BinaryJedisPubSub;
import redis.clients.jedis.Jedis;
import redis.clients.util.SafeEncoder;

/**
 * @author FY
 */
public class RedisBroadcastChannel extends BinaryJedisPubSub implements CacheExpiredListener, CacheBroadcastChannel {
    private static final Logger logger = LoggerFactory.getLogger(RedisBroadcastChannel.class);

    private Base4jCacheFactory factory;
    private String clusterName;

    private final Thread threadSubscribe;
//    private static final RedisBroadcastChannel subscribe = new RedisBroadcastChannel();

    public RedisBroadcastChannel(final String clusterName, final Base4jCacheFactory factory) {
        this.factory = factory;
        this.clusterName = clusterName;

        try {
            long startTime = System.currentTimeMillis();
            threadSubscribe = new Thread(new Runnable() {
                @Override
                public void run() {
                    Jedis jedis = SuperCacheProvider.getResource();
                    jedis.subscribe(RedisBroadcastChannel.this, SafeEncoder.encode(clusterName));
                    SuperCacheProvider.returnResource(jedis);
                }
            });
            threadSubscribe.start();

            logger.info("成功创建缓存广播通道(Redis pub/sub) : {}, 耗时 : {}", clusterName, System.currentTimeMillis() - startTime);
        } catch (Exception e) {
            throw new CacheException("初始化Redis Subscribe线程失败.", e);
        }

    }

    @Override
    public void onDeleteCacheKey(String region, Object key) throws CacheException {
        if (key instanceof List) {
            factory.getProvider(CacheCustoms.CACHE_LV_1).buildCache(region, true, this).evict((List) key);
        } else {
            factory.getProvider(CacheCustoms.CACHE_LV_1).buildCache(region, true, this).evict(key);
        }
    }

    @Override
    public void sendCmdBroadcast(byte optKey, String region, Object key) throws CacheException {
        Command cmd = new Command(optKey, region, key);

        Jedis jedis = SuperCacheProvider.getResource();
        try {
            jedis.publish(SafeEncoder.encode(clusterName), cmd.toBuff());
        } catch (Exception e) {
            logger.error("发送 代码为 [{}] 的 Redis Pub/Sub 事件消息失败 -> region:{}, key:{}", optKey, region, key, e);
        } finally {
            SuperCacheProvider.returnResource(jedis);
        }
    }

    @Override
    public void notifyElementExpired(String region, Object key) {
        logger.debug("缓存数据过期 -> region:{}, key:{}", region, key);

        // 1.清除二级缓存
        if (factory.isOpenSecondCache()) {
            if (key instanceof List) {
                factory.getProvider(CacheCustoms.CACHE_LV_2).buildCache(region, false, null).evict((List) key);
            } else {
                factory.getProvider(CacheCustoms.CACHE_LV_2).buildCache(region, false, null).evict(key);
            }
        }

        // 2.推送清除缓存的广播消息
        if (factory.isUseCluster() && BroadcastType.REDIS_PUBSUB.equals(factory.getCacheBroadcast())) {
            sendCmdBroadcast(CacheCustoms.OPT_DELTED_KEY, region, key);
        }
    }

    /**
     * 消息接受处理
     * @param channel 缓存的通道名称
     * @param message 消息数据
     */
    @Override
    public void onMessage(byte[] channel, byte[] message) {

        // 过滤无效消息
        if (message == null || message.length <= 0) {
            logger.warn("Redis subscribe message is empty!");
            return ;
        }

        try {
            Command cmd = Command.parse(message);
            if (cmd == null) {
                return ;
            }

            switch (cmd.getOperator()) {
                case CacheCustoms.OPT_DELTED_KEY:
                    onDeleteCacheKey(cmd.getRegion(), cmd.getKey());
                    break;
                default:
                    logger.warn("尚未支持的消息类型 : {}", cmd.getOperator());
            }
        } catch (Exception e) {
            logger.error("未能正确处理接收到的JGroup消息.", e);
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy