当前位置: 首页 > news >正文

Redis 使用场景

1、分布式锁

在实际项目中,建议直接使用 Redisson,它提供了完善的分布式锁实现(包括可重入、公平锁、红锁等):

RLock lock = redisson.getLock("myLock");
lock.lock(); // 自动续期(watchdog)
try {// 业务逻辑
} finally {lock.unlock();
}

 Java 分布式锁实现

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;import java.util.Collections;
import java.util.UUID;public class RedisDistributedLock {private final JedisPool jedisPool;private final String lockKey;private final int expireTimeMs; // 锁自动过期时间(毫秒)private String lockValue;       // 当前客户端持有的唯一标识private static final String LOCK_SUCCESS = "OK";private static final Long RELEASE_SUCCESS = 1L;// Lua 脚本:只有 value 匹配才删除锁(原子操作)private static final String UNLOCK_SCRIPT ="if redis.call('get', KEYS[1]) == ARGV[1] then " +"   return redis.call('del', KEYS[1]) " +"else " +"   return 0 " +"end";public RedisDistributedLock(JedisPool jedisPool, String lockKey, int expireTimeMs) {this.jedisPool = jedisPool;this.lockKey = lockKey;this.expireTimeMs = expireTimeMs;}/*** 尝试获取锁(非阻塞)*/public boolean tryLock() {Jedis jedis = null;try {jedis = jedisPool.getResource();lockValue = UUID.randomUUID().toString();// SET key value NX PX expireTimeString result = jedis.set(lockKey, lockValue, "NX", "PX", expireTimeMs);return LOCK_SUCCESS.equals(result);} catch (Exception e) {// 日志记录异常(此处简化)e.printStackTrace();return false;} finally {if (jedis != null) {jedis.close();}}}/*** 阻塞式获取锁,带超时时间(单位:毫秒)*/public boolean lock(long timeoutMs) {long start = System.currentTimeMillis();while (true) {if (tryLock()) {return true;}// 等待一段时间再重试try {Thread.sleep(20); // 20ms 轮询} catch (InterruptedException e) {Thread.currentThread().interrupt();return false;}// 检查是否超时if (System.currentTimeMillis() - start > timeoutMs) {return false;}}}/*** 释放锁(必须由持有者调用)*/public boolean unlock() {if (lockValue == null) {return false;}Jedis jedis = null;try {jedis = jedisPool.getResource();Object result = jedis.eval(UNLOCK_SCRIPT, Collections.singletonList(lockKey),Collections.singletonList(lockValue));return RELEASE_SUCCESS.equals(result);} catch (Exception e) {e.printStackTrace();return false;} finally {if (jedis != null) {jedis.close();}lockValue = null; // 清空标识}}// ===== 可选:支持 try-with-resources 的方式使用锁 =====public AutoCloseableLock autoLock(long timeoutMs) {return new AutoCloseableLock(timeoutMs);}public class AutoCloseableLock implements AutoCloseable {private final boolean locked;public AutoCloseableLock(long timeoutMs) {this.locked = lock(timeoutMs);if (!locked) {throw new RuntimeException("Failed to acquire lock: " + lockKey);}}@Overridepublic void close() {if (locked) {unlock();}}}
}

使用示例

public class DistributedLockExample {public static void main(String[] args) {// 配置 Jedis 连接池(假设 Redis 在本地)JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(10);JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379);String lockKey = "order:process:123";RedisDistributedLock lock = new RedisDistributedLock(jedisPool, lockKey, 10000); // 10秒过期// 方式一:手动加锁/解锁if (lock.lock(5000)) { // 最多等待5秒try {System.out.println("获取锁成功,执行业务逻辑...");Thread.sleep(2000); // 模拟耗时操作} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();System.out.println("锁已释放");}} else {System.out.println("未能在5秒内获取锁");}// 方式二:使用 try-with-resources(推荐)try (RedisDistributedLock.AutoCloseableLock autoLock = lock.autoLock(5000)) {System.out.println("进入临界区(自动管理锁)");Thread.sleep(1000);} catch (Exception e) {System.err.println("加锁失败或业务异常: " + e.getMessage());}// 关闭连接池jedisPool.close();}
}

2、缓存

以下例子基于 Spring Boot + RedisTemplate

配置 RedisTemplate(支持 JSON 序列化)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);// 使用 String 序列化 keytemplate.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 使用 JSON 序列化 value(支持复杂对象)template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());template.afterPropertiesSet();return template;}
}

缓存服务类(核心逻辑)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;@Service
public class UserService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate UserRepository userRepository; // 假设这是你的数据库访问层private static final String USER_CACHE_PREFIX = "user:";/*** 根据 ID 查询用户(带缓存)*/public User getUserById(Long id) {if (id == null) return null;String cacheKey = USER_CACHE_PREFIX + id;// 1. 先查缓存User user = (User) redisTemplate.opsForValue().get(cacheKey);if (user != null) {System.out.println("命中缓存: " + cacheKey);return user;}// 2. 缓存未命中,查数据库user = userRepository.findById(id);if (user != null) {// 3. 写入缓存(设置过期时间,防止雪崩)redisTemplate.opsForValue().set(cacheKey, user, 30, TimeUnit.MINUTES);System.out.println("缓存写入: " + cacheKey);} else {// 4. 防止缓存穿透:对空结果也缓存(短时间)redisTemplate.opsForValue().set(cacheKey, "", 2, TimeUnit.MINUTES);}return user;}/*** 更新用户(先更新 DB,再删除缓存 —— Cache-Aside 模式)*/public void updateUser(User user) {// 1. 更新数据库userRepository.update(user);// 2. 删除缓存(比更新缓存更安全,避免脏数据)String cacheKey = USER_CACHE_PREFIX + user.getId();redisTemplate.delete(cacheKey);System.out.println("缓存已删除: " + cacheKey);}/*** 删除用户*/public void deleteUser(Long id) {userRepository.deleteById(id);redisTemplate.delete(USER_CACHE_PREFIX + id);}
}

http://www.dtcms.com/a/589693.html

相关文章:

  • 针对动态连接场景的验证环境搭建思路
  • 网页制作与网站建设答案专业建设汇报ppt
  • 机器学习21:可解释机器学习(Explainable Machine Learning)(上)
  • 深圳开发网站建设哪家好软件仓库
  • 潍坊网站建设团队微信开放平台小程序
  • Vue 项目实战《尚医通》,根据等级和地区获取医院信息,笔记14
  • C语言关键字详解
  • SmartResume简历信息抽取框架深度解析
  • 2.4 使用 PyTorch / TensorFlow 实现文本分类
  • 传统企业网站建设运营分析闵行区个人网页设计用户体验
  • 从随机变量到统计模型(二)
  • AIGC|北京AI优化企业新榜单与选择指南
  • 站长工具怎么用北京建网站 优帮云
  • files-to-prompt 简介
  • 计算机软件开发网站建设取什么名字营销型外贸网站定制
  • 实战:搭建一个简单的股票价格监控和警报系统
  • 在 Unreal VR 项目中用双目立体全景天空盒优化性能与沉浸感
  • 专业网站推广引流电子商务网站建设与实例
  • 个人免费网站申请关键词挖掘查询工具
  • 学习周报二十一
  • 公司网站建设劳伦网店代运营收费
  • 云南 旅游 网站建设山东嘉邦家居用品公司网站 加盟做经销商多少钱 有人做过吗
  • 触摸未来2025-11-09:万有力,图论革命
  • 做物流哪个网站推广效果好外贸网站的推广技巧有哪些
  • 舞钢市城市建设局网站模板王字体网
  • C++14常用新特性
  • 使用n8n搭建服务器监控系统:从Webhook到Telegram告警的完整实现
  • 如何在Dev-C++中启用调试模式?
  • 高校两学一做网站建设装修公司网站建设设计作品
  • Linux复习:操作系统管理本质:“先描述,再组织”,贯穿软硬件的核心思想