大家好,欢迎来到IT知识分享网。
学习时间: 4-5小时 学习目标: 掌握 Redis 高级特性,学会分布式缓存设计,理解缓存一致性策略
详细学习清单
✅ 第一部分:Redis高级数据结构与应用(60分钟)
1. Redis高级数据结构详解
Redis 数据结构应用场景
package com.example.demo.redis; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import java.util.*; #技术分享 public class RedisDataStructuresDemo { private JedisPool jedisPool; public RedisDataStructuresDemo() { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(20); config.setMaxIdle(10); config.setMinIdle(5); config.setTestOnBorrow(true); config.setTestOnReturn(true); config.setTestWhileIdle(true); this.jedisPool = new JedisPool(config, "localhost", 6379); } public void stringOperations() { try (Jedis jedis = jedisPool.getResource()) { System.out.println("=== 字符串操作 ==="); jedis.set("user:1001:name", "张三"); jedis.set("user:1001:age", "25"); jedis.setex("user:1001:token", 3600, "abc123token"); jedis.set("page:views", "0"); jedis.incr("page:views"); jedis.incrBy("page:views", 10); jedis.decr("page:views"); Map<String, String> userInfo = new HashMap<>(); userInfo.put("name", "李四"); userInfo.put("age", "30"); userInfo.put("email", ""); jedis.hmset("user:1002", userInfo); System.out.println("页面访问量: " + jedis.get("page:views")); System.out.println("用户信息: " + jedis.hgetAll("user:1002")); } } public void hashOperations() { try (Jedis jedis = jedisPool.getResource()) { System.out.println("\n=== 哈希操作 ==="); jedis.hset("user:1003", "id", "1003"); jedis.hset("user:1003", "name", "王五"); jedis.hset("user:1003", "age", "28"); jedis.hset("user:1003", "city", "北京"); String userName = jedis.hget("user:1003", "name"); System.out.println("用户名: " + userName); Map<String, String> allFields = jedis.hgetAll("user:1003"); System.out.println("用户完整信息: " + allFields); boolean hasEmail = jedis.hexists("user:1003", "email"); System.out.println("是否有邮箱: " + hasEmail); jedis.hdel("user:1003", "age"); System.out.println("删除年龄后的信息: " + jedis.hgetAll("user:1003")); } } public void listOperations() { try (Jedis jedis = jedisPool.getResource()) { System.out.println("\n=== 列表操作 ==="); jedis.lpush("messages:user:1001", "消息1", "消息2", "消息3"); jedis.lpush("messages:user:1001", "消息4"); List<String> latestMessages = jedis.lrange("messages:user:1001", 0, 4); System.out.println("最新消息: " + latestMessages); jedis.rpush("task:queue", "任务 A", "任务 B", "任务 C"); String task = jedis.lpop("task:queue"); System.out.println("处理任务: " + task); System.out.println("剩余任务: " + jedis.lrange("task:queue", 0, -1)); long listLength = jedis.llen("messages:user:1001"); System.out.println("消息列表长度: " + listLength); } } public void setOperations() { try (Jedis jedis = jedisPool.getResource()) { System.out.println("\n=== 集合操作 ==="); jedis.sadd("user:1001:tags", "VIP", "活跃用户", "北京用户"); jedis.sadd("user:1002:tags", "普通用户", "活跃用户", "上海用户"); jedis.sadd("user:1003:tags", "VIP", "新用户", "北京用户"); Set<String> userTags = jedis.smembers("user:1001:tags"); System.out.println("用户1001标签: " + userTags); Set<String> commonTags = jedis.sinter("user:1001:tags", "user:1003:tags"); System.out.println("用户1001和1003共同标签: " + commonTags); Set<String> allTags = jedis.sunion("user:1001:tags", "user:1002:tags", "user:1003:tags"); System.out.println("所有用户标签: " + allTags); Set<String> diffTags = jedis.sdiff("user:1001:tags", "user:1002:tags"); System.out.println("用户1001独有标签: " + diffTags); jedis.sadd("online:users", "1001", "1002", "1003"); boolean isOnline = jedis.sismember("online:users", "1001"); System.out.println("用户1001是否在线: " + isOnline); } } public void sortedSetOperations() { try (Jedis jedis = jedisPool.getResource()) { System.out.println("\n=== 有序集合操作 ==="); jedis.zadd("user:score:rank", 1000, "user:1001"); jedis.zadd("user:score:rank", 1500, "user:1002"); jedis.zadd("user:score:rank", 800, "user:1003"); jedis.zadd("user:score:rank", 2000, "user:1004"); Set<String> topUsers = jedis.zrevrange("user:score:rank", 0, 2); System.out.println("积分排行榜前3名: " + topUsers); Long rank = jedis.zrevrank("user:score:rank", "user:1002"); System.out.println("用户1002排名: " + (rank != null ? rank + 1 : "未上榜")); Set<String> scoreRangeUsers = jedis.zrangeByScore("user:score:rank", 1000, 1500); System.out.println("积分1000-1500的用户: " + scoreRangeUsers); jedis.zincrby("user:score:rank", 500, "user:1001"); Double newScore = jedis.zscore("user:score:rank", "user:1001"); System.out.println("用户1001新积分: " + newScore); jedis.zadd("article:likes:rank", 50, "article:001"); jedis.zadd("article:likes:rank", 30, "article:002"); jedis.zadd("article:likes:rank", 80, "article:003"); Set<String> popularArticles = jedis.zrevrange("article:likes:rank", 0, 2); System.out.println("热门文章: " + popularArticles); } } public void bitmapOperations() { try (Jedis jedis = jedisPool.getResource()) { System.out.println("\n=== 位图操作 ==="); String today = "2024-01-15"; String yesterday = "2024-01-14"; jedis.setbit("sign:user:1001:" + today, 0, true); jedis.setbit("sign:user:1001:" + yesterday, 0, true); jedis.setbit("sign:user:1002:" + today, 0, true); boolean hasSigned = jedis.getbit("sign:user:1001:" + today, 0); System.out.println("用户1001今天是否签到: " + hasSigned); long signCount = jedis.bitcount("sign:user:1001:" + today); System.out.println("用户1001今日签到次数: " + signCount); int consecutiveDays = 0; for (int i = 0; i < 7; i++) { String date = "2024-01-" + (15 - i); if (jedis.getbit("sign:user:1001:" + date, 0)) { consecutiveDays++; } else { break; } } System.out.println("用户1001连续签到天数: " + consecutiveDays); } } public static void main(String[] args) { RedisDataStructuresDemo demo = new RedisDataStructuresDemo(); demo.stringOperations(); demo.hashOperations(); demo.listOperations(); demo.setOperations(); demo.sortedSetOperations(); demo.bitmapOperations(); } }
2. Redis发布订阅模式
Redis 发布订阅实现
package com.example.demo.redis; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPubSub; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class RedisPubSubDemo { private JedisPool jedisPool; private ExecutorService executorService; public RedisPubSubDemo() { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(20); config.setMaxIdle(10); config.setMinIdle(5); this.jedisPool = new JedisPool(config, "localhost", 6379); this.executorService = Executors.newFixedThreadPool(5); } public void publishMessages() { try (Jedis jedis = jedisPool.getResource()) { System.out.println("=== 消息发布者 ==="); jedis.publish("order:events", "订单创建: ORDER-001"); jedis.publish("order:events", "订单支付: ORDER-001"); jedis.publish("order:events", "订单完成: ORDER-001"); jedis.publish("user:events", "用户注册: USER-1001"); jedis.publish("user:events", "用户登录: USER-1001"); jedis.publish("system:alerts", "系统维护通知"); jedis.publish("system:alerts", "数据库连接异常"); System.out.println("消息发布完成"); } } public void subscribeOrderEvents() { executorService.submit(() -> { try (Jedis jedis = jedisPool.getResource()) { jedis.subscribe(new JedisPubSub() { @Override public void onMessage(String channel, String message) { System.out.println("订单事件订阅者收到消息: [" + channel + "] " + message); if (message.contains("订单创建")) { handleOrderCreated(message); } else if (message.contains("订单支付")) { handleOrderPaid(message); } else if (message.contains("订单完成")) { handleOrderCompleted(message); } } @Override public void onSubscribe(String channel, int subscribedChannels) { System.out.println("订阅订单事件频道: " + channel); } @Override public void onUnsubscribe(String channel, int subscribedChannels) { System.out.println("取消订阅订单事件频道: " + channel); } }, "order:events"); } catch (Exception e) { e.printStackTrace(); } }); } public void subscribeUserEvents() { executorService.submit(() -> { try (Jedis jedis = jedisPool.getResource()) { jedis.subscribe(new JedisPubSub() { @Override public void onMessage(String channel, String message) { System.out.println("用户事件订阅者收到消息: [" + channel + "] " + message); if (message.contains("用户注册")) { handleUserRegistered(message); } else if (message.contains("用户登录")) { handleUserLoggedIn(message); } } @Override public void onSubscribe(String channel, int subscribedChannels) { System.out.println("订阅用户事件频道: " + channel); } }, "user:events"); } catch (Exception e) { e.printStackTrace(); } }); } public void subscribeSystemAlerts() { executorService.submit(() -> { try (Jedis jedis = jedisPool.getResource()) { jedis.subscribe(new JedisPubSub() { @Override public void onMessage(String channel, String message) { System.out.println("系统告警订阅者收到消息: [" + channel + "] " + message); handleSystemAlert(message); } @Override public void onSubscribe(String channel, int subscribedChannels) { System.out.println("订阅系统告警频道: " + channel); } }, "system:alerts"); } catch (Exception e) { e.printStackTrace(); } }); } private void handleOrderCreated(String message) { System.out.println("处理订单创建事件: " + message); } private void handleOrderPaid(String message) { System.out.println("处理订单支付事件: " + message); } private void handleOrderCompleted(String message) { System.out.println("处理订单完成事件: " + message); } private void handleUserRegistered(String message) { System.out.println("处理用户注册事件: " + message); } private void handleUserLoggedIn(String message) { System.out.println("处理用户登录事件: " + message); } private void handleSystemAlert(String message) { System.out.println("处理系统告警: " + message); } public static void main(String[] args) throws InterruptedException { RedisPubSubDemo demo = new RedisPubSubDemo(); demo.subscribeOrderEvents(); demo.subscribeUserEvents(); demo.subscribeSystemAlerts(); Thread.sleep(2000); demo.publishMessages(); Thread.sleep(3000); demo.executorService.shutdown(); } }
✅ 第二部分:Spring Boot Redis集成(90分钟)
1. Redis配置与连接池
Redis 配置类
package com.example.demo.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import java.time.Duration; @Configuration public class RedisConfig { @Value("${spring.redis.host:localhost}") private String host; @Value("${spring.redis.port:6379}") private int port; @Value("${spring.redis.password:}") private String password; @Value("${spring.redis.database:0}") private int database; @Value("${spring.redis.timeout:2000}") private int timeout; @Value("${spring.redis.lettuce.pool.max-active:20}") private int maxActive; @Value("${spring.redis.lettuce.pool.max-idle:10}") private int maxIdle; @Value("${spring.redis.lettuce.pool.min-idle:5}") private int minIdle; @Value("${spring.redis.lettuce.pool.max-wait:2000}") private long maxWait; @Bean public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration(); redisConfig.setHostName(host); redisConfig.setPort(port); redisConfig.setPassword(password); redisConfig.setDatabase(database); GenericObjectPoolConfig<Object> poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxTotal(maxActive); poolConfig.setMaxIdle(maxIdle); poolConfig.setMinIdle(minIdle); poolConfig.setMaxWaitMillis(maxWait); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); LettucePoolingClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder() .poolConfig(poolConfig) .commandTimeout(Duration.ofMillis(timeout)) .shutdownTimeout(Duration.ofMillis(100)) .build(); return new LettuceConnectionFactory(redisConfig, clientConfig); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(mapper); StringRedisSerializer stringSerializer = new StringRedisSerializer(); template.setKeySerializer(stringSerializer); template.setValueSerializer(serializer); template.setHashKeySerializer(stringSerializer); template.setHashValueSerializer(serializer); template.setEnableTransactionSupport(true); template.afterPropertiesSet(); return template; } @Bean public RedisTemplate<String, String> stringRedisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, String> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); StringRedisSerializer stringSerializer = new StringRedisSerializer(); template.setKeySerializer(stringSerializer); template.setValueSerializer(stringSerializer); template.setHashKeySerializer(stringSerializer); template.setHashValueSerializer(stringSerializer); template.afterPropertiesSet(); return template; } }
2. Redis工具类
Redis 工具类
package com.example.demo.util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.*; import java.util.concurrent.TimeUnit; @Component public class RedisUtil { @Autowired private RedisTemplate<String, Object> redisTemplate; public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } public boolean hasKey(String key) { try { return Boolean.TRUE.equals(redisTemplate.hasKey(key)); } catch (Exception e) { e.printStackTrace(); return false; } } @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public long incr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } public long decr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } public Object hget(String key, String item) { return redisTemplate.opsForHash().get(key, item); } public Map<Object, Object> hmget(String key) { return redisTemplate.opsForHash().entries(key); } public boolean hmset(String key, Map<String, Object> map) { try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean hmset(String key, Map<String, Object> map, long time) { try { redisTemplate.opsForHash().putAll(key, map); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean hset(String key, String item, Object value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean hset(String key, String item, Object value, long time) { try { redisTemplate.opsForHash().put(key, item, value); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public void hdel(String key, Object... item) { redisTemplate.opsForHash().delete(key, item); } public boolean hHasKey(String key, String item) { return redisTemplate.opsForHash().hasKey(key, item); } public Set<Object> sGet(String key) { try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } public boolean sHasKey(String key, Object value) { try { return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value)); } catch (Exception e) { e.printStackTrace(); return false; } } public long sSet(String key, Object... values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } public long sSetAndTime(String key, long time, Object... values) { try { Long count = redisTemplate.opsForSet().add(key, values); if (time > 0) { expire(key, time); } return count; } catch (Exception e) { e.printStackTrace(); return 0; } } public long sGetSetSize(String key) { try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } public long setRemove(String key, Object... values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } public List<Object> lGet(String key, long start, long end) { try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } public long lGetListSize(String key) { try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } public Object lGetIndex(String key, long index) { try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } public boolean lSet(String key, Object value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean lSet(String key, Object value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean lSet(String key, List<Object> value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean lSet(String key, List<Object> value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean lUpdateIndex(String key, long index, Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public long lRemove(String key, long count, Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } public boolean zAdd(String key, Object value, double score) { try { return Boolean.TRUE.equals(redisTemplate.opsForZSet().add(key, value, score)); } catch (Exception e) { e.printStackTrace(); return false; } } public long zCard(String key) { try { return redisTemplate.opsForZSet().zCard(key); } catch (Exception e) { e.printStackTrace(); return 0; } } public Double zScore(String key, Object value) { try { return redisTemplate.opsForZSet().score(key, value); } catch (Exception e) { e.printStackTrace(); return null; } } public Set<Object> zRange(String key, long start, long end) { try { return redisTemplate.opsForZSet().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } public Set<Object> zRangeByScore(String key, double min, double max) { try { return redisTemplate.opsForZSet().rangeByScore(key, min, max); } catch (Exception e) { e.printStackTrace(); return null; } } public boolean lock(String key, String value, long expireTime) { try { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " + "return redis.call('del', KEYS[1]) " + "else " + "return 0 " + "end"; DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(); redisScript.setScriptText(script); redisScript.setResultType(Long.class); Long result = redisTemplate.execute(redisScript, Collections.singletonList(key), value); return result != null && result == 1; } catch (Exception e) { e.printStackTrace(); return false; } } public boolean tryLock(String key, String value, long expireTime) { try { Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS); return Boolean.TRUE.equals(result); } catch (Exception e) { e.printStackTrace(); return false; } } }
3. 缓存服务实现
缓存服务类
package com.example.demo.service; import com.example.demo.util.RedisUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Slf4j @Service public class CacheService { @Autowired private RedisUtil redisUtil; @Autowired private ObjectMapper objectMapper; public void cacheUserInfo(Long userId, Object userInfo) { String key = "user:info:" + userId; try { String json = objectMapper.writeValueAsString(userInfo); redisUtil.set(key, json, 3600); log.info("缓存用户信息成功: {}", userId); } catch (JsonProcessingException e) { log.error("缓存用户信息失败: {}", userId, e); } } public <T> T getUserInfo(Long userId, Class<T> clazz) { String key = "user:info:" + userId; Object value = redisUtil.get(key); if (value != null) { try { return objectMapper.readValue(value.toString(), clazz); } catch (JsonProcessingException e) { log.error("获取用户信息失败: {}", userId, e); } } return null; } public void cacheProductInfo(Long productId, Object productInfo) { String key = "product:info:" + productId; try { String json = objectMapper.writeValueAsString(productInfo); redisUtil.set(key, json, 1800); log.info("缓存商品信息成功: {}", productId); } catch (JsonProcessingException e) { log.error("缓存商品信息失败: {}", productId, e); } } public <T> T getProductInfo(Long productId, Class<T> clazz) { String key = "product:info:" + productId; Object value = redisUtil.get(key); if (value != null) { try { return objectMapper.readValue(value.toString(), clazz); } catch (JsonProcessingException e) { log.error("获取商品信息失败: {}", productId, e); } } return null; } public void cacheHotData(String dataType, String dataKey, Object data) { String key = "hot:data:" + dataType + ":" + dataKey; try { String json = objectMapper.writeValueAsString(data); redisUtil.set(key, json, 600); log.info("缓存热点数据成功: {}:{}", dataType, dataKey); } catch (JsonProcessingException e) { log.error("缓存热点数据失败: {}:{}", dataType, dataKey, e); } } public <T> T getHotData(String dataType, String dataKey, Class<T> clazz) { String key = "hot:data:" + dataType + ":" + dataKey; Object value = redisUtil.get(key); if (value != null) { try { return objectMapper.readValue(value.toString(), clazz); } catch (JsonProcessingException e) { log.error("获取热点数据失败: {}:{}", dataType, dataKey, e); } } return null; } public void deleteCache(String key) { redisUtil.del(key); log.info("删除缓存成功: {}", key); } public void deleteCacheByPattern(String pattern) { log.info("批量删除缓存: {}", pattern); } public long incrementCounter(String key, long delta) { return redisUtil.incr(key, delta); } public long getCounter(String key) { Object value = redisUtil.get(key); return value != null ? Long.parseLong(value.toString()) : 0; } public void setCounterExpire(String key, long seconds) { redisUtil.expire(key, seconds); } }
✅ 第三部分:分布式缓存一致性(90分钟)
1. 缓存一致性策略
缓存一致性策略实现
package com.example.demo.cache; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; @Slf4j @Component public class CacheConsistencyStrategy { @Autowired private RedisTemplate<String, Object> redisTemplate; public class CacheAsideStrategy { public <T> T read(String cacheKey, Class<T> clazz, DataLoader<T> dataLoader) { T cachedData = (T) redisTemplate.opsForValue().get(cacheKey); if (cachedData != null) { log.info("缓存命中: {}", cacheKey); return cachedData; } log.info("缓存未命中,从数据库读取: {}", cacheKey); T data = dataLoader.load(); if (data != null) { redisTemplate.opsForValue().set(cacheKey, data, 3600, TimeUnit.SECONDS); log.info("数据写入缓存: {}", cacheKey); } return data; } public <T> void write(String cacheKey, T data, DataWriter<T> dataWriter) { dataWriter.write(data); log.info("数据写入数据库: {}", cacheKey); redisTemplate.delete(cacheKey); log.info("删除缓存: {}", cacheKey); } } public class WriteThroughStrategy { public <T> void write(String cacheKey, T data, DataWriter<T> dataWriter) { redisTemplate.opsForValue().set(cacheKey, data, 3600, TimeUnit.SECONDS); log.info("数据写入缓存: {}", cacheKey); dataWriter.write(data); log.info("数据写入数据库: {}", cacheKey); } public <T> T read(String cacheKey, Class<T> clazz) { T data = (T) redisTemplate.opsForValue().get(cacheKey); if (data != null) { log.info("缓存命中: {}", cacheKey); } else { log.info("缓存未命中: {}", cacheKey); } return data; } } public class WriteBehindStrategy { public <T> void write(String cacheKey, T data) { redisTemplate.opsForValue().set(cacheKey, data, 3600, TimeUnit.SECONDS); log.info("数据写入缓存: {}", cacheKey); asyncWriteToDatabase(cacheKey, data); } private <T> void asyncWriteToDatabase(String cacheKey, T data) { log.info("异步写入数据库: {}", cacheKey); } } public class DoubleDeleteStrategy { public <T> void update(String cacheKey, T data, DataWriter<T> dataWriter) { redisTemplate.delete(cacheKey); log.info("第一次删除缓存: {}", cacheKey); dataWriter.write(data); log.info("更新数据库: {}", cacheKey); delayDeleteCache(cacheKey); } private void delayDeleteCache(String cacheKey) { new Thread(() -> { try { Thread.sleep(1000); redisTemplate.delete(cacheKey); log.info("延迟删除缓存: {}", cacheKey); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/188356.html