flea-cache使用之Redis分片模式接入

article/2025/9/30 17:03:01

Redis分片模式接入

  • 1. 参考
  • 2. 依赖
  • 3. 基础接入
    • 3.1 定义Flea缓存接口
    • 3.2 定义抽象Flea缓存类
    • 3.3 定义Redis客户端接口类
    • 3.4 定义Redis客户端命令行
    • 3.5 定义分片模式Redis客户端实现类
    • 3.6 定义Redis分片连接池
    • 3.7 Redis配置文件
    • 3.8 定义Redis Flea缓存类
    • 3.9 定义抽象Flea缓存管理类
    • 3.10 定义Redis分片模式Flea缓存管理类
    • 3.11 定义Redis客户端工厂类
    • 3.12 定义 Redis 客户端策略上下文
    • 3.13 定义分片模式 Redis 客户端策略
    • 3.14 Redis接入自测
  • 4. 进阶接入
    • 4.1 定义抽象Spring缓存
    • 4.2 定义Redis Spring缓存类
    • 4.3 定义抽象Spring缓存管理类
    • 4.4 定义Redis分片模式Spring缓存管理类
    • 4.5 spring 配置
    • 4.6 缓存自测
  • 结语

1. 参考

flea-cache使用之Redis分片模式接入 源代码
在这里插入图片描述

2. 依赖

jedis-3.0.1.jar

<!-- Java redis -->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.0.1</version>
</dependency>

spring-context-4.3.18.RELEASE.jar

<!-- Spring相关 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.18.RELEASE</version>
</dependency>

spring-context-support-4.3.18.RELEASE.jar

<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>4.3.18.RELEASE</version>
</dependency>

3. 基础接入

3.1 定义Flea缓存接口

IFleaCache 可参考笔者的这篇博文 Memcached接入,不再赘述。

3.2 定义抽象Flea缓存类

AbstractFleaCache 可参考笔者的这篇博文 Memcached接入,不再赘述。

3.3 定义Redis客户端接口类

RedisClient , 注意该版,相比《flea-frame-cache使用之Redis接入》博文中,废弃如下与 ShardedJedis 有关的方法:

	ShardedJedisPool getJedisPool();void setShardedJedis(ShardedJedis shardedJedis);ShardedJedis getShardedJedis();

《flea-frame-cache使用之Redis接入》博文中 提到了使用 Redis客户端代理方式 访问 RedisClient, 在这版为了实现Redis访问异常后的重试机制,废弃了代理模式,采用了命令行模式,可参考下面的 RedisClientCommand

3.4 定义Redis客户端命令行

RedisClientCommand 封装了使用ShardedJedis操作Redis缓存的公共逻辑

/*** Redis客户端命令行,封装了使用ShardedJedis操作Redis缓存的公共逻辑,* 如果出现异常可以重试{@code maxAttempts} 次。** <p> 抽象方法 {@code execute},由子类或匿名类实现。在实际调用前,* 需要从分布式Jedis连接池中获取分布式Jedis对象;调用结束后,* 关闭分布式Jedis对象,归还给分布式Jedis连接池。** @author huazie* @version 1.1.0* @since 1.1.0*/
public abstract class RedisClientCommand<T> {private static final FleaLogger LOGGER = FleaLoggerProxy.getProxyInstance(RedisClientCommand.class);private final ShardedJedisPool shardedJedisPool; // 分布式Jedis连接池private final int maxAttempts; // Redis客户端操作最大尝试次数【包含第一次操作】public RedisClientCommand(ShardedJedisPool shardedJedisPool, int maxAttempts) {this.shardedJedisPool = shardedJedisPool;this.maxAttempts = maxAttempts;}public abstract T execute(ShardedJedis connection);/*** 执行分布式Jedis操作** @return 分布式Jedis对象操作的结果* @since 1.0.0*/public T run() {return runWithRetries(this.maxAttempts);}/*** 执行分布式Jedis操作,如果出现异常,包含第一次操作,可最多尝试maxAttempts次。** @param attempts 重试次数* @return 分布式Jedis对象操作的结果* @since 1.0.0*/private T runWithRetries(int attempts) {if (attempts <= 0) {throw new FleaCacheMaxAttemptsException("No more attempts left.");}ShardedJedis connection = null;try {connection = shardedJedisPool.getResource();Object obj = null;if (LOGGER.isDebugEnabled()) {obj = new Object() {};LOGGER.debug1(obj, "Get ShardedJedis = {}", connection);}T result = execute(connection);if (LOGGER.isDebugEnabled()) {LOGGER.debug1(obj, "Result = {}", result);}return result;} catch (JedisConnectionException e) {// 在开始下一次尝试前,释放当前分布式Jedis的连接,将分布式Jedis对象归还给分布式Jedis连接池releaseConnection(connection);connection = null; // 这里置空是为了最后finally不重复操作if (LOGGER.isErrorEnabled()) {Object obj = new Object() {};LOGGER.error1(obj, "Redis连接异常:", e);int currAttempts = this.maxAttempts - attempts + 1;LOGGER.error1(obj, "第 {} 次尝试失败,开始第 {} 次尝试...", currAttempts, currAttempts + 1);}return runWithRetries(attempts - 1);} finally {releaseConnection(connection);}}/*** 释放指定分布式Jedis的连接,将分布式Jedis对象归还给分布式Jedis连接池** @param connection 分布式Jedis实例* @since 1.0.0*/private void releaseConnection(ShardedJedis connection) {if (ObjectUtils.isNotEmpty(connection)) {if (LOGGER.isDebugEnabled()) {LOGGER.debug1(new Object() {}, "Close ShardedJedis");}connection.close();}}
}

3.5 定义分片模式Redis客户端实现类

FleaRedisShardedClient 主要使用 ShardedJedis 来操作 Redis 数据。

/*** Flea分片模式Redis客户端实现类,封装了Flea框架操作Redis缓存的基本操作。** <p> 它内部具体操作Redis缓存的功能,由分布式Jedis对象完成,* 包含读、写、删除Redis缓存的基本操作方法。* * 详见笔者 https://github.com/Huazie/flea-frame,欢迎 Star** @author huazie* @version 1.1.0* @since 1.0.0*/
public class FleaRedisShardedClient extends FleaRedisClient {private ShardedJedisPool shardedJedisPool; // 分布式Jedis连接池private int maxAttempts; // Redis客户端操作最大尝试次数【包含第一次操作】/*** <p> Redis客户端构造方法 (默认连接池名) </p>** @since 1.0.0*/private FleaRedisShardedClient() {this(CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME);}/*** <p> Redis客户端构造方法(指定连接池名) </p>** @param poolName 连接池名* @since 1.0.0*/private FleaRedisShardedClient(String poolName) {super(poolName);init();}/*** <p> 初始化分布式Jedis连接池 </p>** @since 1.0.0*/private void init() {if (CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME.equals(getPoolName())) {shardedJedisPool = RedisShardedPool.getInstance().getJedisPool();maxAttempts = RedisShardedConfig.getConfig().getMaxAttempts();} else {shardedJedisPool = RedisShardedPool.getInstance(getPoolName()).getJedisPool();maxAttempts = CacheConfigUtils.getMaxAttempts();}}@Overridepublic String set(final String key, final Object value) {return new RedisClientCommand<String>(this.shardedJedisPool, this.maxAttempts) {@Overridepublic String execute(ShardedJedis connection) {if (value instanceof String)return connection.set(key, (String) value);elsereturn connection.set(SafeEncoder.encode(key), ObjectUtils.serialize(value));}}.run();}@Overridepublic String set(final byte[] key, final byte[] value) {// 省略。。。。。。}@Overridepublic String set(final String key, final Object value, final int expiry) {// 省略。。。。。。}@Overridepublic String set(final byte[] key, final byte[] value, final int expiry) {// 省略。。。。。。}@Overridepublic String set(final String key, final Object value, final long expiry) {// 省略。。。。。。}@Overridepublic String set(final byte[] key, final byte[] value, final long expiry) {// 省略。。。。。。}@Overridepublic String set(final String key, final Object value, final SetParams params) {// 省略。。。。。。}@Overridepublic String set(final byte[] key, final byte[] value, final SetParams params) {// 省略。。。。。。}@Overridepublic byte[] get(final byte[] key) {// 省略。。。。。。}@Overridepublic Long del(final String key) {// 省略。。。。。。}/*** <p> 获取客户端类 </p>** @param key 数据键* @return 客户端类* @since 1.0.0*/@Overrideprotected Client getClientByKey(final Object key) {// 省略。。。。。。}/*** <p> 内部建造者类 </p>*/public static class Builder {// 省略。。。。。。}
}

该类的构造函数初始化逻辑,可以看出我们使用了 RedisShardedPool, 下面来介绍一下。

3.6 定义Redis分片连接池

RedisShardedPool ,上个版本我们使用 RedisPool 初始化Redis相关配置信息,为了体现Redis分片模式,这个版本里面,我们使用 RedisShardedPool 用于Redis相关配置信息的初始化,其中重点是获取分布式Jedis连接池 ShardedJedisPool ,该类其中一个构造方法如下:

/*** @param poolConfig 连接池配置信息* @param shards Jedis分布式服务器列表* @param algo 分布式算法*/
public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards,Hashing algo) 
/*** Redis分片连接池,用于初始化分布式 Jedis 连接池。** <p> 针对单独缓存接入场景,采用默认连接池初始化的方式;<br/>* 可参考如下:* <pre>*   // 初始化默认连接池*   RedisShardedPool.getInstance().initialize(); </pre>** <p> 针对整合缓存接入场景,采用指定连接池初始化的方式;<br/>* 可参考如下:* <pre>*   // 初始化指定连接池*   RedisShardedPool.getInstance(group).initialize(cacheServerList); </pre>** @author huazie* @version 1.1.0* @since 1.0.0*/
public class RedisShardedPool {private static final ConcurrentMap<String, RedisShardedPool> redisPools = new ConcurrentHashMap<>();private String poolName; // 连接池名private ShardedJedisPool shardedJedisPool; // 分布式Jedis连接池private RedisShardedPool(String poolName) {this.poolName = poolName;}/*** <p> 获取Redis连接池实例 (默认连接池) </p>** @return Redis连接池实例对象* @since 1.0.0*/public static RedisShardedPool getInstance() {return getInstance(CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME);}/*** <p> 获取Redis连接池实例 (指定连接池名) </p>** @param poolName 连接池名* @return Redis连接池实例对象* @since 1.0.0*/public static RedisShardedPool getInstance(String poolName) {if (!redisPools.containsKey(poolName)) {synchronized (redisPools) {if (!redisPools.containsKey(poolName)) {RedisShardedPool redisShardedPool = new RedisShardedPool(poolName);redisPools.putIfAbsent(poolName, redisShardedPool);}}}return redisPools.get(poolName);}/*** <p> 默认初始化 </p>** @since 1.0.0*/public void initialize() {// 省略。。。。。。}/*** <p> 初始化 (非默认连接池) </p>** @param cacheServerList 缓存服务器集* @since 1.0.0*/public void initialize(List<CacheServer> cacheServerList) {// 省略。。。。。。}/*** <p> 获取当前连接池名 </p>** @return 连接池名* @since 1.0.0*/public String getPoolName() {return poolName;}/*** <p> 分布式Jedis连接池 </p>** @return 分布式Jedis连接池* @since 1.0.0*/public ShardedJedisPool getJedisPool() {if (ObjectUtils.isEmpty(shardedJedisPool)) {throw new FleaCacheConfigException("获取分布式Jedis连接池失败:请先调用initialize初始化");}return shardedJedisPool;}
}

3.7 Redis配置文件

flea-cache读取 redis.properties(Redis配置文件),用作初始化 RedisShardedPool

# Redis配置
# Redis缓存所属系统名
redis.systemName=FleaFrame# Redis服务器地址
redis.server=127.0.0.1:10001,127.0.0.1:10002,127.0.0.1:10003# Redis服务登录密码
redis.password=huazie123,huazie123,huazie123# Redis服务器权重分配
redis.weight=1,1,1# Redis客户端socket连接超时时间(单位:ms)
redis.connectionTimeout=2000# Redis客户端socket读写超时时间(单位:ms)
redis.soTimeout=2000# Redis分布式hash算法
# 1 : MURMUR_HASH
# 2 : MD5
redis.hashingAlg=1# Redis客户端连接池配置
# Jedis连接池最大连接数
redis.pool.maxTotal=100# Jedis连接池最大空闲连接数
redis.pool.maxIdle=10# Jedis连接池最小空闲连接数
redis.pool.minIdle=0# Jedis连接池获取连接时的最大等待时间(单位:ms)
redis.pool.maxWaitMillis=2000# Redis客户端操作最大尝试次数【包含第一次操作】
redis.maxAttempts=5# 空缓存数据有效期(单位:s)
redis.nullCacheExpiry=10

3.8 定义Redis Flea缓存类

RedisFleaCache 继承抽象Flea缓存类 AbstractFleaCache ,其构造方法可见如需要传入Redis客户端 RedisClient ,相关使用下面介绍:

/*** Redis Flea缓存类,实现了以Flea框架操作Redis缓存的基本操作方法。** <p> 在上述基本操作方法中,实际使用Redis客户端【{@code redisClient}】* 读、写和删除Redis缓存。其中写缓存方法【{@code putNativeValue}】在* 添加的数据值为【{@code null}】时,默认添加空缓存数据【{@code NullCache}】* 到Redis中,有效期取初始化参数【{@code nullCacheExpiry}】。** <p> 单个缓存接入场景,有效期配置可查看【redis.properties】中的配置参数* 【redis.nullCacheExpiry】** <p> 整合缓存接入场景,有效期配置可查看【flea-cache-config.xml】中的缓存参数* 【{@code <cache-param key="fleacore.nullCacheExpiry"* desc="空缓存数据有效期(单位:s)">300</cache-param>}】** @author huazie* @version 1.1.0* @since 1.0.0*/
public class RedisFleaCache extends AbstractFleaCache {private static final FleaLogger LOGGER = FleaLoggerProxy.getProxyInstance(RedisFleaCache.class);private RedisClient redisClient; // Redis客户端private CacheModeEnum cacheMode; // 缓存模式【分片模式和集群模式】/*** <p> 带参数的构造方法,初始化Redis Flea缓存类 </p>** @param name            缓存数据主关键字* @param expiry          缓存数据有效期(单位:s)* @param nullCacheExpiry 空缓存数据有效期(单位:s)* @param cacheMode       缓存模式【分分片模式和集群模式】* @param redisClient     Redis客户端* @since 1.0.0*/public RedisFleaCache(String name, int expiry, int nullCacheExpiry, CacheModeEnum cacheMode, RedisClient redisClient) {super(name, expiry, nullCacheExpiry);this.cacheMode = cacheMode;this.redisClient = redisClient;if (CacheUtils.isClusterMode(cacheMode))cache = CacheEnum.RedisCluster; // 缓存实现之Redis集群模式elsecache = CacheEnum.RedisSharded; // 缓存实现之Redis分片模式}@Overridepublic Object getNativeValue(String key) {if (LOGGER.isDebugEnabled()) {LOGGER.debug1(new Object() {}, "KEY = {}", key);}return redisClient.get(key);}@Overridepublic Object putNativeValue(String key, Object value, int expiry) {if (LOGGER.isDebugEnabled()) {Object obj = new Object() {};LOGGER.debug1(obj, "REDIS FLEA CACHE, KEY = {}", key);LOGGER.debug1(obj, "REDIS FLEA CACHE, VALUE = {}", value);LOGGER.debug1(obj, "REDIS FLEA CACHE, EXPIRY = {}s", expiry);LOGGER.debug1(obj, "REDIS FLEA CACHE, NULL CACHE EXPIRY = {}s", getNullCacheExpiry());}if (ObjectUtils.isEmpty(value)) {return redisClient.set(key, new NullCache(key), getNullCacheExpiry());} else {if (expiry == CommonConstants.NumeralConstants.INT_ZERO) {return redisClient.set(key, value);} else {return redisClient.set(key, value, expiry);}}}@Overridepublic Object deleteNativeValue(String key) {if (LOGGER.isDebugEnabled()) {LOGGER.debug1(new Object() {}, "KEY = {}", key);}return redisClient.del(key);}@Overridepublic String getSystemName() {if (CacheUtils.isClusterMode(cacheMode))// 集群模式下获取缓存归属系统名return RedisClusterConfig.getConfig().getSystemName();else// 分片模式下获取缓存归属系统名return RedisShardedConfig.getConfig().getSystemName();}
}

3.9 定义抽象Flea缓存管理类

AbstractFleaCacheManager 可参考笔者的这篇博文 Memcached接入,不再赘述。

3.10 定义Redis分片模式Flea缓存管理类

RedisShardedFleaCacheManager 继承抽象Flea缓存管理类 AbstractFleaCacheManager,构造方法使用了 RedisClientFactory 获取分片模式下默认连接池的Redis客户端 RedisClient,可在 3.11 查看。newCache 方法返回的是 RedisFleaCache 的实例对象,每一类 Redis 缓存数据都对应了一个 RedisFleaCache 的实例对象。

/*** Redis分片模式Flea缓存管理类,用于接入Flea框架管理Redis缓存。** <p> 它的默认构造方法,用于初始化分片模式下默认连接池的Redis客户端,* 这里需要先初始化Redis连接池,默认连接池名为【default】;* 然后通过Redis客户端工厂类来获取Redis客户端。** <p> 方法 {@code newCache} 用于创建一个Redis Flea缓存,* 它里面包含了 读、写、删除 和 清空 缓存的基本操作。** @author huazie* @version 1.1.0* @see RedisFleaCache* @since 1.0.0*/
public class RedisShardedFleaCacheManager extends AbstractFleaCacheManager {private RedisClient redisClient; // Redis客户端/*** <p> 默认构造方法,初始化分片模式下默认连接池的Redis客户端 </p>** @since 1.0.0*/public RedisShardedFleaCacheManager() {// 初始化默认连接池RedisShardedPool.getInstance().initialize();// 获取分片模式下默认连接池的Redis客户端redisClient = RedisClientFactory.getInstance();}@Overrideprotected AbstractFleaCache newCache(String name, int expiry) {int nullCacheExpiry = RedisShardedConfig.getConfig().getNullCacheExpiry();return new RedisFleaCache(name, expiry, nullCacheExpiry, CacheModeEnum.SHARDED, redisClient);}
}

3.11 定义Redis客户端工厂类

RedisClientFactory ,有四种方式获取 Redis 客户端:

  • 一是获取分片模式下默认连接池的 Redis 客户端,应用在单个缓存接入场景【3.10 采用】;
  • 二是获取指定模式下默认连接池的 Redis 客户端,应用在单个缓存接入场景;
  • 三是获取分片模式下指定连接池的 Redis 客户端,应用在整合缓存接入场景;
  • 四是获取指定模式下指定连接池的 Redis 客户端,应用在整合缓存接入场景。

/*** Redis客户端工厂,用于获取Redis客户端。** @author huazie* @version 1.1.0* @since 1.0.0*/
public class RedisClientFactory {private static final ConcurrentMap<String, RedisClient> redisClients = new ConcurrentHashMap<>();private RedisClientFactory() {}/*** 获取分片模式下默认连接池的Redis客户端** @return 分片模式的Redis客户端* @since 1.0.0*/public static RedisClient getInstance() {return getInstance(CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME);}/*** 获取指定模式下默认连接池的Redis客户端** @param mode 缓存模式* @return 指定模式的Redis客户端* @since 1.1.0*/public static RedisClient getInstance(CacheModeEnum mode) {return getInstance(CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME, mode);}/*** 获取分片模式下指定连接池的Redis客户端** @param poolName 连接池名* @return 分片模式的Redis客户端* @since 1.0.0*/public static RedisClient getInstance(String poolName) {return getInstance(poolName, CacheModeEnum.SHARDED);}/*** 获取指定模式下指定连接池的Redis客户端** @param poolName 连接池名* @param mode     缓存模式* @return 指定模式的Redis客户端* @since 1.1.0*/public static RedisClient getInstance(String poolName, CacheModeEnum mode) {String key = StringUtils.strCat(poolName, CommonConstants.SymbolConstants.UNDERLINE, StringUtils.valueOf(mode.getMode()));if (!redisClients.containsKey(key)) {synchronized (redisClients) {if (!redisClients.containsKey(key)) {RedisClientStrategyContext context = new RedisClientStrategyContext(poolName);redisClients.putIfAbsent(key, FleaStrategyFacade.invoke(mode.name(), context));}}}return redisClients.get(key);}
}

在上面 的 getInstance(String poolName, CacheModeEnum mode) 方法中,使用了 RedisClientStrategyContext ,用于定义 Redis 客户端策略上下文。根据不同的缓存模式,就可以找到对应的 Redis 客户端策略。

3.12 定义 Redis 客户端策略上下文

RedisClientStrategyContext 包含了 Redis 分片 和 Redis 集群 相关的客户端策略。

/*** Redis客户端策略上下文** @author huazie* @version 1.1.0* @since 1.1.0*/
public class RedisClientStrategyContext extends FleaStrategyContext<RedisClient, String> {public RedisClientStrategyContext() {super();}public RedisClientStrategyContext(String contextParam) {super(contextParam);}@Overrideprotected Map<String, IFleaStrategy<RedisClient, String>> init() {Map<String, IFleaStrategy<RedisClient, String>> fleaStrategyMap = new HashMap<>();fleaStrategyMap.put(CacheModeEnum.SHARDED.name(), new RedisShardedClientStrategy());fleaStrategyMap.put(CacheModeEnum.CLUSTER.name(), new RedisClusterClientStrategy());return Collections.unmodifiableMap(fleaStrategyMap);}
}

3.13 定义分片模式 Redis 客户端策略

RedisShardedClientStrategy 用于新建分片模式Redis客户端

/*** 分片模式Redis客户端 策略** @author huazie* @version 1.1.0* @since 1.1.0*/
public class RedisShardedClientStrategy implements IFleaStrategy<RedisClient, String> {@Overridepublic RedisClient execute(String poolName) throws FleaStrategyException {RedisClient originRedisClient;// 新建一个Flea Redis客户端类实例if (CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME.equals(poolName)) {originRedisClient = new FleaRedisShardedClient.Builder().build();} else {originRedisClient = new FleaRedisShardedClient.Builder(poolName).build();}return originRedisClient;}
}

好了,到这里我们可以来测试 Redis 分片模式。

3.14 Redis接入自测

单元测试类详见 FleaCacheTest

首先,这里需要按照 Redis 配置文件中的地址部署相应的 Redis 服务,可参考笔者的 这篇博文。

    @Testpublic void testRedisShardedFleaCache() {try {// 分片模式下Flea缓存管理类AbstractFleaCacheManager manager = FleaCacheManagerFactory.getFleaCacheManager(CacheEnum.RedisSharded.getName());AbstractFleaCache cache = manager.getCache("fleaparadetail");LOGGER.debug("Cache={}", cache);//## 1.  简单字符串cache.put("menu1", "huazie");cache.put("menu2", null);
//            cache.get("menu1");
//            cache.get("menu2");
//            cache.delete("menu1");
//            cache.delete("menu2");
//            cache.clear();cache.getCacheKey();LOGGER.debug(cache.getCacheName() + ">>>" + cache.getCacheDesc());} catch (Exception e) {LOGGER.error("Exception:", e);}}

4. 进阶接入

4.1 定义抽象Spring缓存

AbstractSpringCache 可参考笔者的这篇博文 Memcached接入,不再赘述。

4.2 定义Redis Spring缓存类

RedisSpringCache 继承抽象 Spring 缓存 AbstractSpringCache,用于对接 Spring; 从构造方法可见,该类初始化还是使用 RedisFleaCache

/*** Redis Spring缓存类,继承了抽象Spring缓存父类的读、写、删除 和 清空* 缓存的基本操作方法,由Redis Spring缓存管理类初始化。** <p> 它的构造方法中,必须传入一个具体Flea缓存实现类,这里我们使用* Redis Flea缓存【{@code RedisFleaCache}】。** @author huazie* @version 1.1.0* @see RedisFleaCache* @since 1.0.0*/
public class RedisSpringCache extends AbstractSpringCache {/*** <p> 带参数的构造方法,初始化Redis Spring缓存类 </p>** @param name      缓存数据主关键字* @param fleaCache 具体Flea缓存实现* @since 1.0.0*/public RedisSpringCache(String name, IFleaCache fleaCache) {super(name, fleaCache);}/*** <p> 带参数的构造方法,初始化Redis Spring缓存类 </p>** @param name            缓存数据主关键字* @param expiry          缓存数据有效期(单位:s)* @param nullCacheExpiry 空缓存数据有效期(单位:s)* @param cacheMode       缓存模式【分片模式和集群模式】* @param redisClient     Redis客户端* @since 1.0.0*/public RedisSpringCache(String name, int expiry, int nullCacheExpiry, CacheModeEnum cacheMode, RedisClient redisClient) {this(name, new RedisFleaCache(name, expiry, nullCacheExpiry, cacheMode, redisClient));}}

4.3 定义抽象Spring缓存管理类

AbstractSpringCacheManager 可参考笔者的这篇博文 Memcached接入,不再赘述。

4.4 定义Redis分片模式Spring缓存管理类

RedisShardedSpringCacheManager 继承抽象 Spring 缓存管理类 AbstractSpringCacheManager,用于对接Spring; 基本实现同 RedisShardedFleaCacheManager,唯一不同在于 newCache 的实现。

/*** Redis分片模式Spring缓存管理类,用于接入Spring框架管理Redis缓存。** <p> 它的默认构造方法,用于初始化分片模式下默认连接池的Redis客户端,* 这里需要先初始化Redis连接池,默认连接池名为【default】;* 然后通过Redis客户端工厂类来获取Redis客户端。** <p> 方法【{@code newCache}】用于创建一个Redis Spring缓存,* 而它内部是由Redis Flea缓存实现具体的 读、写、删除 和 清空* 缓存的基本操作。** @author huazie* @version 1.1.0* @see RedisSpringCache* @since 1.0.0*/
public class RedisShardedSpringCacheManager extends AbstractSpringCacheManager {private RedisClient redisClient; // Redis客户端/*** <p> 默认构造方法,初始化分片模式下默认连接池的Redis客户端 </p>** @since 1.0.0*/public RedisShardedSpringCacheManager() {// 初始化默认连接池RedisShardedPool.getInstance().initialize();// 获取分片模式下默认连接池的Redis客户端redisClient = RedisClientFactory.getInstance();}@Overrideprotected AbstractSpringCache newCache(String name, int expiry) {int nullCacheExpiry = RedisShardedConfig.getConfig().getNullCacheExpiry();return new RedisSpringCache(name, expiry, nullCacheExpiry, CacheModeEnum.SHARDED, redisClient);}
}

4.5 spring 配置

	<!--配置缓存管理 redisShardedSpringCacheManager配置缓存时间 configMap (key缓存对象名称 value缓存过期时间)--><bean id="redisShardedSpringCacheManager" class="com.huazie.frame.cache.redis.manager.RedisShardedSpringCacheManager"><property name="configMap"><map><entry key="fleaconfigdata" value="86400"/></map></property></bean><!-- 开启缓存 --><cache:annotation-driven cache-manager="redisShardedSpringCacheManager" proxy-target-class="true"/>

4.6 缓存自测

	private ApplicationContext applicationContext;@Beforepublic void init() {applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");LOGGER.debug("ApplicationContext={}", applicationContext);}@Testpublic void testRedisShardedSpringCache() {try {// 分片模式下Spring缓存管理类AbstractSpringCacheManager manager = (RedisShardedSpringCacheManager) applicationContext.getBean("redisShardedSpringCacheManager");LOGGER.debug("RedisCacheManager={}", manager);AbstractSpringCache cache = manager.getCache("fleaconfigdata");LOGGER.debug("Cache={}", cache);Set<String> cacheKey = cache.getCacheKey();LOGGER.debug("CacheKey = {}", cacheKey);//## 1.  简单字符串
//			cache.put("menu1", "huazie");
//            cache.get("menu1");
//            cache.get("menu1", String.class);//## 2.  简单对象(要是可以序列化的对象)
//			String user = new String("huazie");
//			cache.put("user", user);
//			LOGGER.debug(cache.get("user", String.class));
//            cache.get("FLEA_RES_STATE");
//            cache.clear();//## 3.  List塞对象
//			List<String> userList = new ArrayList<>();
//			userList.add("huazie");
//			userList.add("lgh");
//			cache.put("user_list", userList);//			LOGGER.debug(cache.get("user_list",userList.getClass()).toString());} catch (Exception e) {LOGGER.error("Exception:", e);}}

结语

Redis 接入重构工作已经全部结束,当前版本为 Redis 分片模式。下一篇博文,我将要介绍 Redis 集群模式的接入工作,敬请期待!!!


http://chatgpt.dhexx.cn/article/EASIu6YX.shtml

相关文章

java如何实现redis分片存储_Redis的分片机制

前言:大家都知道redis单台的默认内存大小一般是10M.如果现在需要我们将1G的数据保存到内存中。这该如何做到呢?比如我们就用单台redis,但是一味的扩大单台redis内存则直接影响执行的效率,会有一种得不偿失的感觉。于是呢,我们就得采用分片策略实现数据保存,通过多台redis…

Redis分片的实现

1.为什么使用分片 1.1 说明: 虽然redis可以扩展内存空间的大小,但是如果需要存储海量的数据,一味地去扩大内存,其实效率不高. 1.2 分片的介绍 准备多台redis,共同为用户提供缓存服务,在保证效率的前提下,实现了内存的扩容. 用户在使用分片机制时,将多台redis当做一个整体来…

使用DockerCompose部署Redis分片集群——整合SpringBoot

今天来记录一下使用DockerCompose部署Redis分片集群的过程&#xff0c;前面写了几篇关于redis的博客了&#xff0c;这里就不再过多介绍了&#xff0c;直接上配置就好了 version: "3.0"services:redisServer1:image: redis:6.2.4container_name: redis_server1volume…

redis之分片集群

写在前面 当redis单实例存储的数据过多时&#xff0c;比如说20G&#xff0c;就会出现因为生成RDB快照较长时间比如500ms阻塞主线程的问题&#xff0c;在这一段时间里&#xff0c;因为主线程被阻塞&#xff0c;所以Redis实例无法正常的对外提供服务&#xff0c;出现这个问题的原…

Redis分片集群(详解+图)

目录 分片集群特征&#xff1a; 散列插槽 集群伸缩 创建新的redis实例 添加新节点到redis 转移插槽 故障转移 自动故障转移 手动故障转移 RedisTemplate访问分片集群 主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决&#xff1a; 海量数据存储问…

redis分片_Redis分片

redis分片 本文是我们学院课程的一部分&#xff0c;标题为Redis NoSQL键值存储 。 这是Redis的速成课程。 您将学习如何安装Redis和启动服务器。 此外&#xff0c;您还会在Redis命令行上乱七八糟。 接下来是更高级的主题&#xff0c;例如复制&#xff0c;分片和集群&#xff0…

(分布式缓存)Redis分片集群

对应的教程视频: 高级篇Day3-04-Redis分片集群_哔哩哔哩_bilibili 一.搭建分片集群 1.集群结构 分片集群需要的节点数量较多&#xff0c;这里我们搭建一个最小的分片集群&#xff0c;包含3个master节点&#xff0c;每个master包含一个slave节点&#xff0c;结构如下&#xff…

Docker中搭建redis分片集群,搭建redis哨兵结构,实现springboot中对redis分片集群、哨兵结构的访问,Redis缓存雪崩、缓存击穿处理(非关系型数据库技术课程 第十二周)

文章目录 一、要求&#xff1a;二、知识总结缓存雪崩解决方案 docker中redis分片集群搭建配置好配置文件redis-6380.confredis-6381.confredis-6382.confredis-6383.confredis-6384.confredis-6385.conf 将conf_cluster文件夹移动到对应位置docker中运行对应的redis容器docker中…

Redis分片入门案例

说明 由多台redis共同处理用户的业务数据&#xff0c;实现了redis内存数据的动态扩容&#xff0c;称之为分片机制。 特点 多态redis当作一台使用 分片搭建 1、在redis工作目录下创建工作目录 [rootlocalhost redis]# mkdir shards2、把redis配置文件复制到指定目录下 3、…

分布式缓存-Redis分片集群

一、分片集群结构 主从和哨兵可以解决高可用、高并发读的问题&#xff0c;但是依然有两个问题没有解决&#xff1a; 海量数据存储问题高并发写的问题 使用分片集群可以解决上述问题&#xff0c;分片集群特征&#xff1a; 集群中有多个 master&#xff0c;每个 master 保存不…

SpringBoot整合Redis分片

1 编辑分片配置文件 #redis.host192.168.126.129 #redis.port6379 redis.nodes192.168.126.129:6379,192.168.126.129:6380,192.168.126.129:63812 编辑配置类实现redis整合 Configuration //我是一个配置类 一般都会与Bean联用 PropertySource("classpath:/properti…

Redis搭建分片集群

一、什么是Redis分片集群 1、概念 Redis分片集群是用于将Redis的数据分布在多个Redis节点上的分布式系统。通过分片集群&#xff0c;可以将数据分成多个部分&#xff0c;并将每个部分存储在不同的节点上&#xff0c;以便实现Redis的高可用性和高性能。 2、Redis分片集群原理…

Docker下搭建Redis分片集群

分片集群结构 同一台虚拟机中开启6个redis实例&#xff0c;模拟分片集群 IP PORT角色192.168.19.1287001master192.168.19.1287002master192.168.19.1287003master192.168.19.1288001slave192.168.19.1288002slave192.168.19.1288003slave 搭建Redis分片集群 创建实例目录 …

redis分片集群

目录 分片集群结构搭建分片集群散列插槽集群伸缩故障转移 分片集群结构 主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决&#xff1a; 1.海量数据存储问题 2.高并发写的问题使用分片集群可以解决上述问题&#xff0c;分片集群特征&#xff1a; 1.集群…

Redis分区/分片详解

分区/分片详解 分区是分割数据到多个Redis实例的处理过程&#xff0c;因此每个实例只保存key的一个子集。 如果只使用一个redis实例时&#xff0c;其中保存了服务器中全部的缓存数据&#xff0c;这样会有很大风险&#xff0c;如果单台redis服务宕机了将会影响到整个服务。解决的…

Redis(七)--分片技术详解

文章目录 介绍Redis集群的数据分布算法&#xff1a;哈希槽算法集群的请求重定向Redis集群中节点的通信机制&#xff1a;goosip协议介绍原理通信过程优缺点goosip协议的常见类型 集群的扩容与收缩扩容收缩 集群的故障检测与故障恢复机制故障检测故障恢复 介绍 Redis分片&#x…

Redis集群系列五 —— 分区/片概念

什么是分区 分区就是将所存储的数据按照一定的规则存储在不同的存储服务或介质上&#xff0c;通过降低单服务或介质的数据量级来提升数据处理能力&#xff0c;从而达到拥有数据处理横向扩容的能力的目的。 还可简单的理解为分区就是将数据拆分到多个 Redis 实例的过程&#xf…

redis分区(分片)原理

redis相关文章 ----redis原理概述 -----redis集群方案 ----redis分区&#xff08;分片&#xff09;原理 ----Redis实现分布式锁 ----redis缓存穿透、雪崩和解决方案 分区的概念 分区是分割数据到多个Redis实例的处理过程&#xff0c;因此每个实例只保存key的一个子集如果只使…

调和级数近似求和公式推导(转载)

原文链接: https://blog.csdn.net/ezoiHQM/article/details/82961266?utm_mediumdistribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_sourcedistribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonec…