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

io.jboot.components.cache.ehredis.JbootEhredisCacheImpl Maven / Gradle / Ivy

Go to download

Jboot is a similar SpringCloud project base on JFinal, Dubbo and Undertow.

There is a newer version: 4.1.6
Show newest version
/**
 * Copyright (c) 2015-2019, Michael Yang 杨福海 ([email protected]).
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.jboot.components.cache.ehredis; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.jfinal.plugin.ehcache.IDataLoader; import io.jboot.Jboot; import io.jboot.support.redis.JbootRedis; import io.jboot.components.cache.JbootCacheBase; import io.jboot.components.cache.ehcache.JbootEhcacheImpl; import io.jboot.components.cache.redis.JbootRedisCacheImpl; import io.jboot.components.serializer.JbootSerializer; import io.jboot.utils.StrUtil; import net.sf.ehcache.CacheException; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; import net.sf.ehcache.event.CacheEventListener; import redis.clients.jedis.BinaryJedisPubSub; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; /** * 基于 ehcache和redis做的二级缓存 * 优点是:减少高并发下redis的io瓶颈 */ public class JbootEhredisCacheImpl extends JbootCacheBase implements CacheEventListener { public static final String DEFAULT_NOTIFY_CHANNEL = "jboot_ehredis_channel"; private JbootEhcacheImpl ehcacheImpl; private JbootRedisCacheImpl redisCacheImpl; private JbootRedis redis; private JbootSerializer serializer; private String channel = DEFAULT_NOTIFY_CHANNEL; private String clientId; private LoadingCache keysCache = Caffeine.newBuilder() .expireAfterAccess(10, TimeUnit.MINUTES) .expireAfterWrite(10, TimeUnit.MINUTES) .build(key -> null); public JbootEhredisCacheImpl() { this.ehcacheImpl = new JbootEhcacheImpl(); this.ehcacheImpl.setCacheEventListener(this); this.redisCacheImpl = new JbootRedisCacheImpl(); this.clientId = StrUtil.uuid(); this.serializer = Jboot.getSerializer(); this.redis = redisCacheImpl.getRedis(); this.redis.subscribe(new BinaryJedisPubSub() { @Override public void onMessage(byte[] channel, byte[] message) { JbootEhredisCacheImpl.this.onMessage((String) serializer.deserialize(channel), serializer.deserialize(message)); } }, serializer.serialize(channel)); } @Override public List getKeys(String cacheName) { List list = keysCache.getIfPresent(cacheName); if (list == null) { list = redisCacheImpl.getKeys(cacheName); if (list == null) { list = new ArrayList(); } keysCache.put(cacheName, list); } return list; } @Override public T get(String cacheName, Object key) { T value = ehcacheImpl.get(cacheName, key); if (value == null) { value = redisCacheImpl.get(cacheName, key); if (value != null) { Integer ttl = redisCacheImpl.getTtl(cacheName, key); if (ttl != null && ttl > 0) { ehcacheImpl.put(cacheName, key, value, ttl); } else { ehcacheImpl.put(cacheName, key, value); } } } return value; } @Override public void put(String cacheName, Object key, Object value) { try { ehcacheImpl.put(cacheName, key, value); redisCacheImpl.put(cacheName, key, value); } finally { publishMessage(JbootEhredisMessage.ACTION_PUT, cacheName, key); } } @Override public void put(String cacheName, Object key, Object value, int liveSeconds) { if (liveSeconds <= 0) { put(cacheName, key, value); return; } try { ehcacheImpl.put(cacheName, key, value, liveSeconds); redisCacheImpl.put(cacheName, key, value, liveSeconds); } finally { publishMessage(JbootEhredisMessage.ACTION_PUT, cacheName, key); } } @Override public void remove(String cacheName, Object key) { try { ehcacheImpl.remove(cacheName, key); redisCacheImpl.remove(cacheName, key); } finally { publishMessage(JbootEhredisMessage.ACTION_REMOVE, cacheName, key); } } @Override public void removeAll(String cacheName) { try { ehcacheImpl.removeAll(cacheName); redisCacheImpl.removeAll(cacheName); } finally { publishMessage(JbootEhredisMessage.ACTION_REMOVE_ALL, cacheName, null); } } @Override public T get(String cacheName, Object key, IDataLoader dataLoader) { T value = get(cacheName, key); if (value != null) { return value; } value = (T) dataLoader.load(); if (value != null) { put(cacheName, key, value); } return value; } @Override public T get(String cacheName, Object key, IDataLoader dataLoader, int liveSeconds) { if (liveSeconds <= 0) { return get(cacheName, key, dataLoader); } T value = get(cacheName, key); if (value != null) { return value; } value = (T) dataLoader.load(); if (value != null) { put(cacheName, key, value, liveSeconds); } return value; } @Override public Integer getTtl(String cacheName, Object key) { Integer ttl = ehcacheImpl.getTtl(cacheName, key); if (ttl == null) { ttl = redisCacheImpl.getTtl(cacheName, key); } return ttl; } @Override public void setTtl(String cacheName, Object key, int seconds) { try { ehcacheImpl.setTtl(cacheName, key, seconds); redisCacheImpl.setTtl(cacheName, key, seconds); } finally { publishMessage(JbootEhredisMessage.ACTION_REMOVE, cacheName, key); } } private void publishMessage(int action, String cacheName, Object key) { clearKeysCache(cacheName); JbootEhredisMessage message = new JbootEhredisMessage(clientId, action, cacheName, key); redis.publish(serializer.serialize(channel), serializer.serialize(message)); } private void clearKeysCache(String cacheName) { keysCache.invalidate(cacheName); } public void onMessage(String channel, Object obj) { JbootEhredisMessage message = (JbootEhredisMessage) obj; /** * 不处理自己发送的消息 */ if (clientId.equals(message.getClientId())) { return; } clearKeysCache(message.getCacheName()); switch (message.getAction()) { case JbootEhredisMessage.ACTION_PUT: ehcacheImpl.remove(message.getCacheName(), message.getKey()); break; case JbootEhredisMessage.ACTION_REMOVE: ehcacheImpl.remove(message.getCacheName(), message.getKey()); break; case JbootEhredisMessage.ACTION_REMOVE_ALL: ehcacheImpl.removeAll(message.getCacheName()); break; } } public JbootEhcacheImpl getEhcacheImpl() { return ehcacheImpl; } public JbootRedisCacheImpl getRedisCacheImpl() { return redisCacheImpl; } @Override public void notifyElementRemoved(Ehcache cache, Element element) throws CacheException { } @Override public void notifyElementPut(Ehcache cache, Element element) throws CacheException { } @Override public void notifyElementUpdated(Ehcache cache, Element element) throws CacheException { } @Override public void notifyElementExpired(Ehcache cache, Element element) { clearKeysCache(cache.getName()); } @Override public void notifyElementEvicted(Ehcache cache, Element element) { } @Override public void notifyRemoveAll(Ehcache cache) { } @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } @Override public void dispose() { } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy