`

针对基于Redis Cluster的接口数据缓存删除实现

阅读更多
首先定义个工具interface,基于Java 8的实现.
主要利用了Redis Cluster的hashTags特性。详细细节可前往https://redis.io/topics/cluster-spec的Keys hash tags章节了解。
个人建议还是看完这个规范的前半部分才好理解,为什么会出现hash tags这个东西。

package com.xxxx.cms.common.support;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.collections4.CollectionUtils;

import com.google.common.collect.Lists;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.util.JedisClusterCRC16;

public interface RedisCacheSupporter {

	String SEPARATOR = RedisCacheBase.staticSeparator();

	String CONJUNCTION = RedisCacheBase.staticConjunction();

	String PLACEHOLDER = RedisCacheBase.staticPlaceHolder();

	String LEFT_TAG_STR = RedisCacheBase.staticLeftTagStr();

	String RIGHT_TAG_STR = RedisCacheBase.staticRightTagStr();

	static String hashTagsPrefix(String cacheKeyPrefix) {
		
		return LEFT_TAG_STR + cacheKeyPrefix + RIGHT_TAG_STR;
	}
	
	static TreeSet<String> keys(JedisCluster jedisClusterClient, String cachePrefix) {

		Map<String, JedisPool> clusterNodes = jedisClusterClient.getClusterNodes();
		TreeSet<String> keys = new TreeSet<>();
		String strPattern = cachePrefix + "*";
		for (String k : clusterNodes.keySet()) {

			JedisPool jp = clusterNodes.get(k);
			try (Jedis jedis = jp.getResource();) {

				if (jedis.info("replication").contains("role:slave"))
					continue;
				
				Set<String> keysInNode = jedis.keys(strPattern);
				keys.addAll(keysInNode);
			}
		}
		return keys;
	}
	
	static boolean delByKey(JedisCluster jedisClusterClient, String cacheKey) {
		
		return jedisClusterClient.del(cacheKey) > 0;
	}
	
	/**
	 * 缓存前缀通过hash tags {@link #hashTagsPrefix(String)}处理过的key首选使用本方法
	 * <br/>
	 * <br/>
	 * hash tags在redis集群reSharding时,不能保证都在同一slot下,所以为代码健壮性考虑可首先调用本方法再捕获异常中调用{@link #delLoopNodesByPrefix(JedisCluster, String)}方法处理
	 * @param jedisClusterClient
	 * @param cachePrefix
	 */
	static void delAllByPrefix(JedisCluster jedisClusterClient, String cachePrefix) {
		
		Set<String> keys = keys(jedisClusterClient, cachePrefix);
		if (CollectionUtils.isEmpty(keys)) {
			
			return;
		}
		
		jedisClusterClient.del(keys.toArray(new String[keys.size()]));
	}
	
	static void delLoopNodesByPrefix(JedisCluster jedisClusterClient, String cachePrefix) {

		String keysPattern = cachePrefix + "*";
		Map<String, JedisPool> clusterNodes = jedisClusterClient.getClusterNodes();
		for (String k : clusterNodes.keySet()) {

			JedisPool jedisPool = clusterNodes.get(k);
			try (Jedis jedis = jedisPool.getResource()) {

				if (jedis.info("replication").contains("role:slave"))
					continue;// 从节点不处理

				Set<String> keys = jedis.keys(keysPattern);
				if (keys.size() <= 0)
					continue;

				Map<Integer, List<String>> map = new HashMap<>();
				for (String key : keys) {

					// cluster模式执行多key操作的时候,这些key必须在同一个slot上
					// 不然会报:redis.clients.jedis.exceptions.JedisClusterException:
					// No way to dispatch this command to Redis Cluster because keys have different slots.
					int slot = JedisClusterCRC16.getSlot(key);
					// 按slot将key分组,相同slot的key一起提交
					if (map.containsKey(slot)) {
						map.get(slot).add(key);
					} else {
						map.put(slot, Lists.newArrayList(key));
					}
				}

				for (Integer slotKey : map.keySet()) {
					jedis.del(map.get(slotKey).toArray(new String[map.get(slotKey).size()]));
				}
			}
		}
	}
	
}




然后后面是针对同一接口的不同分页的缓存数据的key的设置,配合hash tags 的操作。

package com.xxxxx.cms.stock.common.support;

import com.xxxxx.cms.common.support.RedisCacheSupporter;

import redis.clients.jedis.JedisCluster;

public interface CachePrefix {

	String BASE_PREFIX = "cms:stock:plate:";

	interface interfaceSpc {
		
		String PREFIX = BASE_PREFIX + "interface" + RedisCacheSupporter.SEPARATOR;
		
		static String contents(String plateCode) {
			
			return RedisCacheSupporter.hashTagsPrefix(PREFIX + "contents" + RedisCacheSupporter.SEPARATOR + plateCode + RedisCacheSupporter.SEPARATOR);
		}
		
		static void delCotentsAllCache(JedisCluster jedisClusterClient, String plateCode) {
			
			try {
				
				RedisCacheSupporter.delAllByPrefix(jedisClusterClient, contents(plateCode));
			} catch (Exception e) {
				
				e.printStackTrace();
				RedisCacheSupporter.delLoopNodesByPrefix(jedisClusterClient, contents(plateCode));
			}
		}
		
	}

}



分享到:
评论

相关推荐

    一种高效的Redis Cluster的分布式缓存系统.pdf

    本研究工作基于Redis4.0设计并实现了一种RedisCluster分布式缓存系统。该系统在数据分布式存储的基础上,增加了动态扩展能力,通过在不同节点间分布数据,实现系统的线性可扩展性、负载均衡、并发处理、数据吞吐量及...

    rediscluster.rar

    Redis Cluster是Redis官方提供的分布式解决方案,它允许用户在多个节点之间分发数据,从而实现高可用性和水平扩展。本文将详细介绍Redis Cluster的工作原理、配置、使用以及与MySQL数据库的配合。 **一、Redis ...

    RedisCluster集群(Spring访问Redis)

    本文将详细介绍RedisCluster集群的架构及原理,并探讨如何通过Spring Data Redis模块实现对Redis Cluster的访问。 ### 1. RedisCluster集群概述 Redis Cluster是Redis官方提供的分布式解决方案,它将数据分片到多...

    .net基于Redis cluster的分布式Session演示程序应用

    为了解决这个问题,我们可以利用Redis作为分布式缓存系统,并通过Redis Cluster实现Session的分布式存储。下面将详细介绍如何在.NET中基于Redis Cluster实现分布式Session。 **Redis的介绍** Redis是一个开源的、高...

    Redis高可用集群Redis Cluster搭建

    Redis Cluster 的主要用途是实现数据分片(Data Sharding),同时也可以实现高可用(HA)。与 Redis Sentinel 模式相比,Redis Cluster 模式可以减少冗余,提高内存利用率。 1. Redis Cluster 概念 Redis Cluster ...

    Flasher为国内某大型一线电商平台的分布式缓存框架,基于Redis Cluster实现的Java客户端.zip

    该框架是基于Redis Cluster构建的,这意味着它利用了Redis的分布式特性来处理大量的数据存储和检索需求,从而提高了服务的响应速度和系统的整体性能。 Redis Cluster是一个原生的分布式数据库系统,它将数据分散...

    jfinal redis cluster plugin-JFinal redis cluster集群插件

    使用JFinal Redis Cluster插件时,首先需要将其引入到项目中,这里我们看到有一个名为 "jfinal-rediscluster-plugin-by-shixiaotian-0.0.1.jar" 的文件,这应该是该插件的可执行版本。通常,开发者会将这个JAR文件...

    codis/redis 迁移redis cluster工具

    而Codis是阿里巴巴开源的一个分布式Redis解决方案,通过Proxy代理实现多实例的统一访问,解决了单个Redis实例无法满足大规模并发和大容量数据的问题。 Codis到Redis Cluster的迁移工具支持将已经在Codis集群中的...

    25_你能聊聊redis cluster集群模式的原理吗?.zip

    总结,Redis Cluster提供了一种强大的分布式缓存解决方案,通过数据分片和主从复制实现高可用和可扩展性。在Java开发中,合理地使用Redis Cluster可以提升应用的性能和稳定性。需要注意的是,理解和掌握其工作原理...

    基于 redis-rb 的 Redis Cluster Ruby 客户端.zip

    创建新实例要创建新的 Redis 集群实例,请使用startup_nodes = [ {:host =&gt; "127.0.0.1", :port =&gt; 6379}, {:host =&gt; "127.0.0.1", :port =&gt; 6380}]max_cached_connections = 2rc = RedisCluster.new(startup_nodes,...

    RedisCluster.zip

    RedisCluster是Redis的一种分布式集群解决方案,它允许将数据分散存储在多个节点上,以实现高可用性和可扩展性。在RedisCluster中,每个节点都存储一部分数据,并且负责处理一部分客户端请求,这样可以分摊服务器...

    RedisCluster.rar

    RedisCluster 是一个分布式数据库系统,基于 Redis 的集群解决方案,提供了数据分片、高可用性和读写扩展性。本文将深入探讨 RedisCluster 的搭建过程、基本使用方法以及如何在 SpringBoot 应用中进行集成。 首先,...

    Redis-Cluster20161110

    Redis Cluster是Redis的分布式解决方案,它允许数据在多个节点之间分片,提供高可用性和水平扩展性。在Redis Cluster中,数据不是存储在一个单一的服务器上,而是分散在多个节点上,每个节点负责一部分键空间。这种...

    redis高可用笔记,包括RedisCluster集群方式和完全纯手写Redis缓存框架

    Redis Cluster是Redis官方提供的分布式解决方案,通过数据分片(Sharding)实现水平扩展。在Redis Cluster中,数据被分割成多个槽(Slots),每个节点负责一部分槽的存储。当客户端进行操作时,根据哈希算法确定数据...

    Redis-Cluster集群模式部署

    Redis Cluster 集群模式部署 本文将详细介绍 Redis Cluster 集群模式部署的步骤和配置过程。Redis Cluster 是 Redis 的一个高可用解决方案,通过将多个 Redis 节点组合成集群,提高 Redis 的可用性和性能。 环境...

    rediscluster集群demo

    本示例“rediscluster集群demo”旨在展示如何设置和操作一个简单的Redis Cluster实例,确保在本地环境中的正确运行。 首先,Redis Cluster采用无中心架构,每个节点都是对等的,并且负责一部分数据。它通过槽(slot...

    redisCluster.zip

    区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。 Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类...

    redis-cluster-5.0.7.tar.gz

    Redis Cluster是Redis的分布式解决方案,它允许你在多个节点之间分发数据,从而实现高可用性和可扩展性。在本压缩包“redis-cluster-5.0.7.tar.gz”中,我们将探讨Redis Cluster的配置和使用。 首先,`redis-...

    Redis Cluster部署文档.docx

    Redis Cluster 是 Redis 3.0 版本引入的一项重要特性,它允许用户将 Redis 实例分组形成一个集群来提供高可用性和数据分区能力。通过这种方式,可以有效地提高系统的水平扩展能力,并确保即使某个节点出现故障,服务...

Global site tag (gtag.js) - Google Analytics