/** * 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.List; import java.util.Random; import org.pinus4j.cache.ISecondCache; import org.pinus4j.cluster.resources.ShardingDBResource; import org.pinus4j.utils.SecurityUtil; import org.pinus4j.utils.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MemCachedSecondCacheImpl extends AbstractMemCachedCache implements ISecondCache { /** * 日志. */ public static final Logger LOG = LoggerFactory.getLogger(MemCachedSecondCacheImpl.class); private static final Random r = new Random(); /** * 构造方法. * * @param servers ip:port,ip:port */ public MemCachedSecondCacheImpl(String s, int expire) { super(s, expire); } @Override public void putGlobal(String whereKey, String clusterName, String tableName, List data) { if (StringUtil.isBlank(whereKey) || data == null || data.isEmpty()) { return; } try { String versionKey = _buildGlobalVersion(clusterName, tableName); int version = r.nextInt(10000); if (!_exists(versionKey)) { this.memClient.incr(versionKey, 0, version); } else { version = Integer.parseInt((String) this.memClient.get(versionKey)); } String cacheKey = _buildGlobalCacheKey(whereKey, clusterName, tableName, version); this.memClient.set(cacheKey, expire, data); if (LOG.isDebugEnabled()) { LOG.debug("[SECOND CACHE] - put to cache done, key: " + cacheKey); } } catch (Exception e) { LOG.warn("operate second cache failure"); } } @Override public List getGlobal(String whereKey, String clusterName, String tableName) { if (StringUtil.isBlank(whereKey)) { return null; } try { String versionKey = _buildGlobalVersion(clusterName, tableName); if (_exists(versionKey)) { int version = Integer.parseInt((String) this.memClient.get(versionKey)); String cacheKey = _buildGlobalCacheKey(whereKey, clusterName, tableName, version); List data = (List) this.memClient.get(cacheKey); if (LOG.isDebugEnabled() && data != null) { LOG.debug("[SECOND CACHE] - key " + cacheKey + " hit"); } return data; } } catch (Exception e) { LOG.warn("operate second cache failure"); } return null; } @Override public void removeGlobal(String clusterName, String tableName) { String versionKey = _buildGlobalVersion(clusterName, tableName); if (_exists(versionKey)) { this.memClient.incr(versionKey, 1); if (LOG.isDebugEnabled()) { LOG.debug("[SECOND CACHE] - " + versionKey + " clean"); } } } @Override public void put(String whereKey, ShardingDBResource db, List data) { if (StringUtil.isBlank(whereKey) || data == null || data.isEmpty()) { return; } try { String versionKey = _buildShardingVersion(db); int version = r.nextInt(10000); if (!_exists(versionKey)) { this.memClient.incr(versionKey, 0, version); } else { version = Integer.parseInt((String) this.memClient.get(versionKey)); } String cacheKey = _buildShardingCacheKey(whereKey, db, version); this.memClient.set(cacheKey, expire, data); if (LOG.isDebugEnabled()) { LOG.debug("[SECOND CACHE] - put to cache done, key: " + cacheKey); } } catch (Exception e) { LOG.warn("operate second cache failure"); } } @Override public List get(String whereKey, ShardingDBResource db) { if (StringUtil.isBlank(whereKey)) { return null; } try { String versionKey = _buildShardingVersion(db); if (_exists(versionKey)) { int version = Integer.parseInt((String) this.memClient.get(versionKey)); String cacheKey = _buildShardingCacheKey(whereKey, db, version); List data = (List) this.memClient.get(cacheKey); if (LOG.isDebugEnabled() && data != null) { LOG.debug("[SECOND CACHE] - key " + cacheKey + " hit"); } return data; } } catch (Exception e) { LOG.warn("operate second cache failure"); } return null; } @Override public void remove(ShardingDBResource db) { String versionKey = _buildShardingVersion(db); if (_exists(versionKey)) { this.memClient.incr(versionKey, 1); if (LOG.isDebugEnabled()) { LOG.debug("[SECOND CACHE] - " + versionKey + " clean"); } } } private boolean _exists(String key) { return this.memClient.get(key) != null; } private String _buildGlobalVersion(String clusterName, String tableName) { StringBuilder versionKey = new StringBuilder("sec.version."); versionKey.append(clusterName).append("."); versionKey.append(tableName); versionKey.append("."); versionKey.append(getCacheVersion(tableName)); return versionKey.toString(); } public String _buildShardingVersion(ShardingDBResource shardingDBResource) { StringBuilder versionKey = new StringBuilder("sec.version."); versionKey.append(shardingDBResource.getClusterName()); versionKey.append("."); versionKey.append(shardingDBResource.getDbName()); versionKey.append("."); versionKey.append(shardingDBResource.getRegionCapacity()); versionKey.append("."); versionKey.append(shardingDBResource.getTableName()).append(shardingDBResource.getTableIndex()); versionKey.append("."); versionKey.append(getCacheVersion(shardingDBResource.getTableName())); return versionKey.toString(); } /** * global second cache key. sec.[clustername].[tablename].[version].hashCode */ private String _buildGlobalCacheKey(String whereKey, String clusterName, String tableName, int version) { StringBuilder cacheKey = new StringBuilder("sec."); cacheKey.append(clusterName).append("."); cacheKey.append(tableName).append("."); cacheKey.append(getCacheVersion(tableName)).append("."); cacheKey.append(version).append("."); cacheKey.append(SecurityUtil.md5(whereKey)); return cacheKey.toString(); } /** * sharding second cache key. sec.[clustername].[startend].[tablename + * tableIndex].[version].hashCode */ private String _buildShardingCacheKey(String whereKey, ShardingDBResource shardingDBResource, int version) { StringBuilder cacheKey = new StringBuilder("sec."); cacheKey.append(shardingDBResource.getClusterName()); cacheKey.append("."); cacheKey.append(shardingDBResource.getDbName()); cacheKey.append("."); cacheKey.append(shardingDBResource.getRegionCapacity()); cacheKey.append("."); cacheKey.append(shardingDBResource.getTableName()).append(shardingDBResource.getTableIndex()); cacheKey.append("."); cacheKey.append(getCacheVersion(shardingDBResource.getTableName())); cacheKey.append("."); cacheKey.append(version).append("."); cacheKey.append(SecurityUtil.md5(whereKey)); return cacheKey.toString(); } }