医疗门户网站管理系统,婚礼设计素材网站,工信部查网站备案,淘宝客网站素材热点Key拆分方案实现
一、核心拆分策略
热点Key拆分的核心思想是将单个高频访问Key分解为多个子Key#xff0c;分散存储到不同Redis节点#xff0c;降低单节点压力。以下是具体实现方案#xff1a;
二、实现方式
1. 业务层哈希分片实现
创建Key分片工具类#xff0c;通…热点Key拆分方案实现
一、核心拆分策略
热点Key拆分的核心思想是将单个高频访问Key分解为多个子Key分散存储到不同Redis节点降低单节点压力。以下是具体实现方案
二、实现方式
1. 业务层哈希分片实现
创建Key分片工具类通过哈希取模方式分散Key
package plus.gaga.infrastructure.redis;import org.springframework.util.StringUtils;public class KeyShardingUtil {// 分片数量建议与Redis节点数保持一致private static final int SHARD_COUNT 16;/*** 生成分片Key* param originalKey 原始Key* param shardParam 分片参数(如用户ID、商品ID等)* return 分片后的Key*/public static String generateShardingKey(String originalKey, String shardParam) {if (StringUtils.isEmpty(originalKey) || StringUtils.isEmpty(shardParam)) {throw new IllegalArgumentException(Key and shardParam cannot be empty);}// 基于分片参数哈希取模int shardIndex Math.abs(shardParam.hashCode()) % SHARD_COUNT;return originalKey :shard: shardIndex;}
}2. 在服务层应用分片Key
修改对热点活动Key进行拆分
// ... existing code ...
import plus.gaga.infrastructure.redis.KeyShardingUtil;Slf4j
Service
public class LotteryStrategyServiceImpl implements LotteryStrategyService {// ... existing code ...Overridepublic boolean tryAcquire(String activityId, String userId) {// 对热点活动ID进行分片String shardingKey KeyShardingUtil.generateShardingKey(limit:strategy: activityId, userId);long timestamp System.currentTimeMillis();String member userId _ timestamp;Long result redisTemplate.execute(rateLimitScript,Collections.singletonList(shardingKey),1000, // 每分片QPStimestamp,member,60 // 窗口时间(秒));return result ! null result 1;}// 热点数据查询示例Overridepublic ActivityVO queryActivity(String activityId, String userId) {// 1. 尝试从本地缓存获取ActivityVO localActivity localCache.get(activityId);if (localActivity ! null) {return localActivity;}// 2. 从Redis分片查询String shardingKey KeyShardingUtil.generateShardingKey(activity: activityId, userId);ActivityPO activityPO (ActivityPO) redisTemplate.opsForValue().get(shardingKey);// 3. 缓存预热到本地if (activityPO ! null) {localCache.put(activityId, convert(activityPO), Duration.ofMinutes(5));return convert(activityPO);}// 4. 从数据库查询并回填缓存activityPO activityMapper.selectById(activityId);if (activityPO ! null) {redisTemplate.opsForValue().set(shardingKey, activityPO, Duration.ofHours(1));localCache.put(activityId, convert(activityPO), Duration.ofMinutes(5));return convert(activityPO);}return null;}
}3. Redis集群配置
在application.yml中配置Redis集群确保分片Key分布到不同节点
spring:redis:cluster:nodes:- 192.168.1.101:6379- 192.168.1.102:6379- 192.168.1.103:6379max-redirects: 3lettuce:pool:max-active: 16max-idle: 8min-idle: 4三、高级优化策略
1. 动态分片调整
实现分片数量动态调整应对流量变化
// 在KeyShardingUtil中添加动态调整方法
public static void setShardCount(int count) {if (count 0) {SHARD_COUNT count;}
}2. 热点检测与自动分片
集成热点Key检测自动对超过阈值的Key进行分片
Component
public class HotKeyMonitor {Autowiredprivate RedisTemplateString, Object redisTemplate;Scheduled(fixedRate 60000) // 每分钟检测一次public void monitorHotKeys() {// 获取Redis热点Key列表ListString hotKeys getHotKeysFromRedis();for (String key : hotKeys) {if (needSharding(key)) {// 自动分片处理shardHotKey(key);}}}
}3. 读写分离增强
结合读写分离将分片读请求分散到从节点
// 配置读写分离RedisTemplate
Bean
public RedisTemplateString, Object readWriteSplitRedisTemplate() {RedisTemplateString, Object template new RedisTemplate();template.setConnectionFactory(readWriteSplitConnectionFactory());// 其他配置...return template;
}四、注意事项
数据一致性拆分后的Key需要同步更新可使用Redis事务或分布式锁保证分片粒度根据业务场景调整分片数量(SHARD_COUNT)建议设置为Redis节点数的2-4倍本地缓存结合Caffeine等本地缓存框架减少跨节点查询监控告警通过Prometheus监控各分片Key的访问频率设置阈值告警回滚机制设计分片失败的降级方案确保系统可用性
通过以上方案可有效将热点Key的访问压力分散到多个Redis节点提升系统整体吞吐量和稳定性。