redis的应用,缓存,分布式锁
- 其他
- 2025-09-02 11:57:01

1.应用 1.1可以用作缓存
作用:提交数据的查询效率,减少对数据库的访问频率
什么数据时候放入缓存1.修改频率高
2.访问频率高的数据
3.对安全系数比较低
如何实现 @Service public class DeptServer { @Autowired private DeptMapper deptMapper; @Autowired private RedisTemplate redisTemplate; public Dept selectById(Integer id){ //查询是否在缓存 ValueOperations forValue = redisTemplate.opsForValue(); Object o = forValue.get("dept::" + id); if(o!=null){ return (Dept) o; } Dept dept = deptMapper.selectById(id); //存储缓存 forValue.set("dept::" + id,dept); return dept; } } 1.1.2缓存注解spring4.0以后,提供了缓存注解,可以使用注解完成缓存功能,无需自己写
1.在配置类中添加缓存配置
@Bean public CacheManager cacheManager(RedisConnectionFactory factory){ RedisSerializer<String> redisSerializer=new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class); //解决缓存查询转换异常问题 ObjectMapper om=new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); //配置序列化(解决乱码的问题),过期时间600s RedisCacheConfiguration config=RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600))//设置过期时间 //设置key序列化方式 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) //设置value序列化方式 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager=RedisCacheManager.builder(factory).cacheDefaults(config).build(); return cacheManager; }2.使用注解@Cacheable
@Service public class DeptServer { @Autowired private DeptMapper deptMapper; //@Cacheable针对查询的,缓存名为"dept::"+id,它的value为返回结果,返回结果为null则不存入,否则存入 @Cacheable(value = "dept",key = "#id") public Dept selectById(Integer id){ Dept dept = deptMapper.selectById(id); return dept; } }3.开启缓存注解
package com.ghx.server; import com.ghx.dao.DeptMapper; import com.ghx.pojo.entity.Dept; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; /** * @author :guo * @date :Created in 2025/2/18 14:22 * @description: * @version: */ @Service public class DeptServer { @Autowired private DeptMapper deptMapper; //@Cacheable针对查询的,缓存名为"dept::"+id,它的value为返回结果,返回结果为null则不存入,否则存入 @Cacheable(value = "dept",key = "#id") public Dept selectById(Integer id){ Dept dept = deptMapper.selectById(id); return dept; } //先执行方法体,再删除缓存 @CacheEvict(value = "dept",key = "#id") public int delete(Integer id){ return deptMapper.deleteById(id); } //先修改数据库,再修改缓存,把dept对象存入 @CachePut(value = "dept",key = "#dept.id") public Dept update(Dept dept){ deptMapper.updateById(dept); return dept; } } package com.ghx.controller; import com.ghx.pojo.entity.Dept; import com.ghx.server.DeptServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** * @author :guo * @date :Created in 2025/2/18 14:24 * @description: * @version: */ @RestController public class DeptController { @Autowired private DeptServer deptServer; @GetMapping("selectById/{id}") public Dept selectById(@PathVariable Integer id) { //@PathVariable获取请求参数的{}参数 return deptServer.selectById(id); } @GetMapping("delete/{id}") public int delete(@PathVariable Integer id) { return deptServer.delete(id); } @PutMapping("update") public Dept update(@RequestBody Dept dept) { return deptServer.update(dept); } } 1.1.3缓存注解 @Cacheable针对查询的,缓存名如"dept::"+id,它的value为返回结果,返回结果为null则不存入,否则存入 @CacheEvict先执行方法体,再删除缓存 @CachePut先修改数据库,再修改缓存,把dept对象存入 1.2可以作为分布式锁synchronized:
lock:接口
实现类:
ReentrantLock:重入锁 ReentrantReadWriteLock:读写分离锁加的为读锁则线程不堵塞
加的是写锁线程堵塞
上面的都是本地锁
本地锁
//如果在单线程下---该功能没有任何问题。 //如果在多线程的情况---jmeter压测工具---发现出现线程安全问题了。==使用锁synchronized ()或lock锁。 //发现使用锁之前没有问题了。但是如果该项目是一个集群。--发现在集群的情况下本地锁【只对当前工程有效】无效了。 //解决方案就是集群工程共用一把锁就行。---可以使用redis来解决问题。 public String decrement(Integer productid) { //根据id查询商品的库存 synchronized (this) { int num = stockDao.findById(productid); if (num > 0) { //修改库存 stockDao.update(productid); System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"); return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"; } else { System.out.println("商品编号为:" + productid + "的商品库存不足。"); return "商品编号为:" + productid + "的商品库存不足。"; } } }手动实现
@Autowired private StringRedisTemplate redisTemplate; public String decrement(Integer productid) { ValueOperations<String,String> forValue = redisTemplate.opsForValue(); //判断是否获取锁 如果程序死机了 ,无法执行完成 //如果代码没有执行完成,会释放锁。 ——开启了一个守护线程,每隔10s检查当前线程是否还持有锁,如果当前线程还持有锁,就重新为当前线程分配30s //分配3次,33次后直接释放锁 Boolean aBoolean = forValue.setIfAbsent("product::" + productid, "~~~~"); if(aBoolean) { try { //根据id查询商品的库存 int num = stockDao.findById(productid); if (num > 0) { //修改库存 stockDao.update(productid); System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"); return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"; } else { System.out.println("商品编号为:" + productid + "的商品库存不足。"); return "商品编号为:" + productid + "的商品库存不足。"; } } finally { redisTemplate.delete("product::" + productid); } } System.out.println("服务器正忙"); return "服务器正忙"; } Redisson每隔10s检查当前线程是否还持有锁,如果当前线程还持有锁,就重新为当前线程分配30s
依赖
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.24.3</version> </dependency> @Autowired private Redisson redisson; public String decrement(Integer productid) { RLock lock = redisson.getLock("product::" + productid); try { //必须为30s lock.lock(30, TimeUnit.SECONDS); //根据id查询商品的库存 int num = stockDao.findById(productid); if (num > 0) { //修改库存 stockDao.update(productid); System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"); return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"; } else { System.out.println("商品编号为:" + productid + "的商品库存不足。"); return "商品编号为:" + productid + "的商品库存不足。"; } } finally { lock.unlock(); } }
redis的应用,缓存,分布式锁由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“redis的应用,缓存,分布式锁”
上一篇
Linux(Ubuntu24.04)源码编译安装OpenCV
下一篇
第三天面试题