/** * Copyright 2014 Duan Bingnan * * 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 org.pinus4j.cache.impl; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.pinus4j.cache.IPrimaryCache; import org.pinus4j.cluster.resources.ShardingDBResource; import org.pinus4j.entity.meta.EntityPK; import org.pinus4j.utils.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Maps; /** * memcached缓存实现. Pinus存储主缓存的实现. 缓存中的数据不设置过期时间,Pinus存储负责缓存与数据库之间的数据一致性. * * @author duanbn */ public class MemCachedPrimaryCacheImpl extends AbstractMemCachedCache implements IPrimaryCache { /** * 日志. */ public static final Logger LOG = LoggerFactory.getLogger(MemCachedPrimaryCacheImpl.class); /** * 构造方法. * * @param servers ip:port,ip:port */ public MemCachedPrimaryCacheImpl(String s, int expire) { super(s, expire); } @Override public void setCountGlobal(String clusterName, String tableName, long count) { String key = buildGlobalCountKey(clusterName, tableName); _setCount(key, count); } @Override public long decrCountGlobal(String clusterName, String tableName, int delta) { String key = buildGlobalCountKey(clusterName, tableName); return _decrCount(key, delta); } @Override public long incrCountGlobal(String clusterName, String tableName, int delta) { String key = buildGlobalCountKey(clusterName, tableName); return _incrCount(key, delta); } @Override public long getCountGlobal(String clusterName, String tableName) { String key = buildGlobalCountKey(clusterName, tableName); return _getCount(key); } @Override public void putGlobal(String clusterName, String tableName, Map<EntityPK, ? extends Object> data) { if (data == null || data.isEmpty()) { return; } List<String> keys = new ArrayList<String>(); List<Object> datas = new ArrayList<Object>(); for (Map.Entry<EntityPK, ? extends Object> entry : data.entrySet()) { keys.add(buildGlobalKey(clusterName, tableName, entry.getKey())); datas.add(entry.getValue()); } _put(keys, datas); } @Override public <T> Map<EntityPK, T> getGlobal(String clusterName, String tableName, EntityPK[] ids) { List<String> keys = new ArrayList<String>(); for (EntityPK id : ids) { String key = buildGlobalKey(clusterName, tableName, id); keys.add(key); } Map<EntityPK, T> result = Maps.newLinkedHashMap(); Map<String, Object> data = _get(keys); if (data != null) { T value = null; for (int i = 0; i < ids.length; i++) { value = (T) data.get(keys.get(i)); if (value != null) result.put(ids[i], value); } } return result; } @Override public void removeGlobal(String clusterName, String tableName, List<EntityPK> ids) { List<String> keys = new ArrayList<String>(); for (EntityPK id : ids) { keys.add(buildGlobalKey(clusterName, tableName, id)); } _remove(keys); } @Override public void setCount(ShardingDBResource db, long count) { String key = buildCountKey(db); _setCount(key, count); } @Override public long decrCount(ShardingDBResource db, long delta) { String key = buildCountKey(db); return _decrCount(key, delta); } @Override public long incrCount(ShardingDBResource db, long delta) { String key = buildCountKey(db); return _incrCount(key, delta); } @Override public long getCount(ShardingDBResource db) { String key = buildCountKey(db); return _getCount(key); } @Override public void put(ShardingDBResource db, Map<EntityPK, ? extends Object> data) { if (data == null || data.isEmpty()) { return; } List<String> keys = new ArrayList<String>(); List<Object> datas = new ArrayList<Object>(); for (Map.Entry<EntityPK, ? extends Object> entry : data.entrySet()) { keys.add(buildKey(db, entry.getKey())); datas.add(entry.getValue()); } _put(keys, datas); } @Override public <T> Map<EntityPK, T> get(ShardingDBResource db, EntityPK[] ids) { Map<EntityPK, T> result = Maps.newLinkedHashMap(); List<String> keys = new ArrayList<String>(); for (EntityPK id : ids) { keys.add(buildKey(db, id)); } Map<String, Object> data = _get(keys); if (data != null) { T value = null; for (int i = 0; i < ids.length; i++) { value = (T) data.get(keys.get(i)); if (value != null) result.put(ids[i], value); } } return result; } @Override public void remove(ShardingDBResource db, List<EntityPK> ids) { List<String> keys = new ArrayList<String>(); for (EntityPK id : ids) { keys.add(buildKey(db, id)); } _remove(keys); } private void _setCount(String key, long count) { try { _removeCount(key); this.memClient.incr(key, 0, count); if (LOG.isDebugEnabled()) { LOG.debug("[PRIMARY CACHE] - " + key + " set count=" + count); } } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } } private void _removeCount(String key) { try { this.memClient.delete(key); if (LOG.isDebugEnabled()) { LOG.debug("[PRIMARY CACHE] - delete " + key); } } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } } private long _decrCount(String key, long delta) { try { if (memClient.get(key) != null) { long count = memClient.decr(key, delta); if (LOG.isDebugEnabled()) { LOG.debug("[PRIMARY CACHE] - decr " + key + " " + delta); } return count; } } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } return -1; } private long _incrCount(String key, long delta) { try { if (memClient.get(key) != null) { long count = memClient.incr(key, delta); if (LOG.isDebugEnabled()) { LOG.debug("[PRIMARY CACHE] - incr " + key + " " + delta); } return count; } } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } return -1; } private long _getCount(String key) { try { String count = (String) memClient.get(key); if (StringUtil.isNotBlank(count)) { if (LOG.isDebugEnabled()) { LOG.debug("[PRIMARY CACHE] - get " + key + " " + count); } return Long.parseLong(count); } } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } return -1l; } private void _put(List<String> keys, List<? extends Object> data) { if (data == null || data.isEmpty()) { return; } try { for (int i = 0; i < keys.size(); i++) { memClient.set(keys.get(i), expire, data.get(i)); } } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } if (LOG.isDebugEnabled()) { LOG.debug("[PRIMARY CACHE] - put (" + keys.size() + ") to cache " + keys); } } private Map<String, Object> _get(List<String> keys) { try { Map<String, Object> dataMap = memClient.getBulk(keys); if (LOG.isDebugEnabled()) { LOG.debug("[PRIMARY CACHE] - get" + keys + " hits = " + dataMap.size()); } return dataMap; } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } return null; } private void _remove(String key) { try { memClient.delete(key); if (LOG.isDebugEnabled()) { LOG.debug("[PRIMARY CACHE] - remove " + key); } } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } } private void _remove(List<String> keys) { try { for (String key : keys) { _remove(key); } } catch (Exception e) { LOG.warn("操作缓存失败:" + e.getMessage()); } } }