1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
| @Service @Slf4j public class UnifiedCacheManager { private final RedisTemplate<String, Object> redisTemplate; private final RandomExpirationCacheManager randomExpirationManager; private final DistributedLockCacheManager lockCacheManager; private final BloomFilterCacheManager bloomFilterManager; private final NullValueCacheManager nullValueManager; private final CircuitBreakerManager circuitBreakerManager; private final MeterRegistry meterRegistry; public UnifiedCacheManager(RedisTemplate<String, Object> redisTemplate, RandomExpirationCacheManager randomExpirationManager, DistributedLockCacheManager lockCacheManager, BloomFilterCacheManager bloomFilterManager, NullValueCacheManager nullValueManager, CircuitBreakerManager circuitBreakerManager, MeterRegistry meterRegistry) { this.redisTemplate = redisTemplate; this.randomExpirationManager = randomExpirationManager; this.lockCacheManager = lockCacheManager; this.bloomFilterManager = bloomFilterManager; this.nullValueManager = nullValueManager; this.circuitBreakerManager = circuitBreakerManager; this.meterRegistry = meterRegistry; } public <T> T get(String key, Class<T> type, Supplier<T> dataLoader, CacheStrategy strategy) { try { switch (strategy) { case NORMAL: return getNormal(key, type, dataLoader); case HOT_DATA: return getHotData(key, type, dataLoader); case BLOOM_FILTER: return getWithBloomFilter(key, type, dataLoader); case CIRCUIT_BREAKER: return getWithCircuitBreaker(key, type, dataLoader); default: return getNormal(key, type, dataLoader); } } catch (Exception e) { log.error("Error in unified cache get", e); meterRegistry.counter("cache.unified.error").increment(); return null; } } private <T> T getNormal(String key, Class<T> type, Supplier<T> dataLoader) { try { Object cachedData = redisTemplate.opsForValue().get(key); if (cachedData != null) { meterRegistry.counter("cache.unified.normal.hit").increment(); return type.cast(cachedData); } meterRegistry.counter("cache.unified.normal.miss").increment(); T data = dataLoader.get(); if (data != null) { randomExpirationManager.setWithRandomExpiration(key, data, Duration.ofMinutes(30)); } else { nullValueManager.setNullValueCache(key); } return data; } catch (Exception e) { log.error("Error in normal cache get", e); return null; } } private <T> T getHotData(String key, Class<T> type, Supplier<T> dataLoader) { return lockCacheManager.getWithDistributedLock(key, type, dataLoader); } private <T> T getWithBloomFilter(String key, Class<T> type, Supplier<T> dataLoader) { return bloomFilterManager.getWithBloomFilter(key, type, dataLoader); } private <T> T getWithCircuitBreaker(String key, Class<T> type, Supplier<T> dataLoader) { return circuitBreakerManager.getWithCircuitBreaker(key, type, fallback); } public void set(String key, Object value, Duration expiration, CacheStrategy strategy) { try { switch (strategy) { case NORMAL: randomExpirationManager.setWithRandomExpiration(key, value, expiration); break; case HOT_DATA: redisTemplate.opsForValue().set(key, value, expiration); break; case CIRCUIT_BREAKER: circuitBreakerManager.setWithCircuitBreaker(key, value, expiration); break; default: randomExpirationManager.setWithRandomExpiration(key, value, expiration); } meterRegistry.counter("cache.unified.set.success").increment(); } catch (Exception e) { log.error("Error in unified cache set", e); meterRegistry.counter("cache.unified.set.error").increment(); } } public <T> Map<String, T> batchGet(List<String> keys, Class<T> type, Function<String, T> dataLoader, CacheStrategy strategy) { Map<String, T> result = new HashMap<>(); for (String key : keys) { try { T data = get(key, type, () -> dataLoader.apply(key), strategy); result.put(key, data); } catch (Exception e) { log.error("Error getting data for key: {}", key, e); } } return result; } public CacheStats getCacheStats() { return CacheStats.builder() .normalHits(meterRegistry.counter("cache.unified.normal.hit").count()) .normalMisses(meterRegistry.counter("cache.unified.normal.miss").count()) .hotDataHits(meterRegistry.counter("cache.distributed_lock.hit").count()) .hotDataMisses(meterRegistry.counter("cache.distributed_lock.miss").count()) .bloomFilterRejected(meterRegistry.counter("cache.bloom_filter.rejected").count()) .bloomFilterCacheHits(meterRegistry.counter("cache.bloom_filter.cache_hit").count()) .nullValueHits(meterRegistry.counter("cache.null_value.hit").count()) .circuitBreakerHits(meterRegistry.counter("cache.circuit_breaker.hit").count()) .circuitBreakerMisses(meterRegistry.counter("cache.circuit_breaker.miss").count()) .errors(meterRegistry.counter("cache.unified.error").count()) .build(); } }
|