redis的使用场景

目录

1. 热点数据缓存

1.1 什么是缓存?

1.2 缓存的原理

1.3 什么样的数据适合放入缓存中

1.4 哪个组件可以作为缓存

1.5 java使用redis如何实现缓存功能

1.5.1 需要的依赖

1.5.2  配置文件

 1.5.3 代码

 1.5.4 发现

1.6 使用缓存注解完成缓存功能

2. 分布式锁

2.1模拟高并发

2.2 使用syn和lock锁

2.3 模拟多服务器

 2.4 nginx代理集群

2.5 使用redis解决分布式锁文件


1. 热点数据缓存

1.1 什么是缓存?

 为了把一些经常访问的数据,放入缓存中以减少对数据库的访问频率。从而减少数据库的压力,提高程序的性能。(内存中存储)

1.2 缓存的原理

1.3 什么样的数据适合放入缓存中

  1. 查询频率高且修改频率低
  2.  数据安全性低

1.4 哪个组件可以作为缓存

  1. redis组件
  2. memory组件
  3. ehcache组件

1.5 java使用redis如何实现缓存功能

1.5.1 需要的依赖

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>

1.5.2  配置文件

server.port=8080#数据源
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/1suo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=12345678#mybatisplus的sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#mapper映射文件
mybatis-plus.mapper-locations=classpath*:mapper/*.xml#redis配置
spring.redis.host=172.16.7.192
spring.redis.port=6379
spring.redis.database=1

 1.5.3 代码

控制层

package com.ls.controller;import com.ls.entity.Clazz;
import com.ls.service.ClazzService;
import com.ls.vo.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** @program: springboot-redis-cache* @description:* @author: 1suo* @create: 2024-07-24 19:56**/
@RestController
@RequestMapping("clazz")
public class ClazzController {@Autowiredprivate ClazzService clazzService;@DeleteMapping("delete")public R delete(Integer id) {return clazzService.delete(id);}@GetMapping("get")public R get(Integer id) {return clazzService.get(id);}@GetMapping("getAll")public R getAll() {return clazzService.getAll();}@PostMapping("save")public R save(@RequestBody Clazz clazz) {return clazzService.save(clazz);}@PutMapping("update")public R update(Clazz clazz) {return clazzService.update(clazz);}
}

业务层

package com.ls.service.impl;import com.ls.dao.ClazzDao;
import com.ls.entity.Clazz;
import com.ls.service.ClazzService;
import com.ls.vo.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import sun.dc.pr.PRError;import java.util.ArrayList;
import java.util.List;/*** @program: springboot-redis-cache* @description:* @author: 1suo* @create: 2024-07-24 19:57**/
@Service
public class ClazzServiceImpl implements ClazzService {@Autowiredprivate ClazzDao clazzDao;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Overridepublic R save(Clazz clazz) {int insert = clazzDao.insert(clazz);return new R(200,"保存成功",clazz);}@Overridepublic R update(Clazz clazz) {int update = clazzDao.updateById(clazz);if (update>0){redisTemplate.opsForValue().set("clazz::" + clazz.getCid(),clazz);}return new R(200,"更新成功",clazz);}@Overridepublic R delete(Integer id) {int delete = clazzDao.deleteById(id);if (delete>0){redisTemplate.delete("clazz::" + id);}return new R(200,"删除成功",id);}@Overridepublic R get(Integer id) {ValueOperations<String, Object> forValue = redisTemplate.opsForValue();Object o = forValue.get("clazz::" + id);if(o!=null){return new R(200,"查询成功",(Clazz)o);}Clazz clazz = clazzDao.selectById(id);if (clazz!=null){forValue.set("clazz::" + id,clazz);}return new R(500,"查询成功",clazz);}@Overridepublic R getAll() {List<Clazz> list = clazzDao.selectList(null);return new R(200,"查询成功",list);}
}

dao层

package com.ls.dao;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ls.entity.Clazz;/*** @program: springboot-redis-cache* @description:* @author: 1suo* @create: 2024-07-25 08:41**/
public interface ClazzDao extends BaseMapper<Clazz> {
}

实体类

package com.ls.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @program: springboot-redis-cache* @description:* @author: 1suo* @create: 2024-07-24 19:56**/
@Data
@NoArgsConstructor
@AllArgsConstructor@TableName("tbl_clazz")
public class Clazz {@TableId(type = IdType.AUTO)private Integer cid;private String cname;
}

 配置类

package com.ls.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){RedisTemplate<String, Object> template = new RedisTemplate<>();//创建redisTemplate对象StringRedisSerializer serializer = new StringRedisSerializer();//字符串序列化对象Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);//Jackson的序列化对象ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);template.setConnectionFactory(factory);
//        key序列化方式template.setKeySerializer(serializer);
//        value序列化template.setValueSerializer(jackson2JsonRedisSerializer);
//        value hashmap序列化template.setHashValueSerializer(jackson2JsonRedisSerializer);template.setKeySerializer(serializer);return template;}
}

@MapperScan("com.ls.dao") 注解,将dao层自动代理为Mapper代理对象。

 1.5.4 发现

业务层代码除了要维护核心业务功能外,额外还要维护缓存的代码。

解决: 使用AOP面向切面编程。(spring框架用aop切面实现)

1.6 使用缓存注解完成缓存功能

必须spring缓存使用的组件。 

config:为解决序列化的问题

 @Beanpublic 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);// 配置序列化(解决乱码的问题),过期时间600秒RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化.disableCachingNullValues();RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();return cacheManager;}

 开启缓存注解

 

 使用

package com.ls.service.impl;import com.ls.dao.ClazzDao;
import com.ls.entity.Clazz;
import com.ls.service.ClazzService;
import com.ls.vo.R;
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.cache.annotation.EnableCaching;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import sun.dc.pr.PRError;import java.util.ArrayList;
import java.util.List;/*** @program: springboot-redis-cache* @description:* @author: 1suo* @create: 2024-07-24 19:57**/
@Service
public class ClazzServiceImpl implements ClazzService {@Autowiredprivate ClazzDao clazzDao;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Overridepublic R save(Clazz clazz) {int insert = clazzDao.insert(clazz);return new R(200,"保存成功",clazz);}@CachePut(cacheNames = "clazz", key = "#clazz.cid")@Overridepublic Clazz update(Clazz clazz) {int update = clazzDao.updateById(clazz);return clazz;}@CacheEvict(cacheNames = "clazz", key = "#id")@Overridepublic R delete(Integer id) {int delete = clazzDao.deleteById(id);return new R(200,"删除成功",id);}@Cacheable(cacheNames = "clazz", key = "#id")@Overridepublic Clazz get(Integer id) {Clazz clazz = clazzDao.selectById(id);return clazz;}@Overridepublic R getAll() {List<Clazz> list = clazzDao.selectList(null);return new R(200,"查询成功",list);}
}

2. 分布式锁

2.1模拟高并发

使用jmeter压测工具:

第一步:

 第二步:

 第三步:

 通过压测发现库存超卖和重卖了,解决办法使用锁

2.2 使用syn和lock锁

public String decrement(Integer productid) {//根据id查询商品的库存int num = stockDao.findById(productid);synchronized (this) {if (num > 0) {//修改库存stockDao.update(productid);System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个");return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个";} else {System.out.println("商品编号为:" + productid + "的商品库存不足。");return "商品编号为:" + productid + "的商品库存不足。";}}}

 上面使用syn和lock虽然解决了并发问题,但是我们未来项目部署时可能要部署集群模式

2.3 模拟多服务器

点击增加一个服务器,同时启动后,实现模拟多服务器。 下面是服务器配置。

 启动俩个服务器:

 2.4 nginx代理集群

下载window版本的nginx实现代理集群。

nginx.conf配置文件:

 通过压测发现本地锁 无效了,使用redis解决分布式锁文件

2.5 使用redis解决分布式锁文件

 核心代码:

@Service
public class StockService {@Autowiredprivate StockDao stockDao;@Autowiredprivate RedissonClient redisson;//public String decrement(Integer productid) {RLock lock = redisson.getLock("product::" + productid);lock.lock();try {//根据id查询商品的库存: 提前预热到redis缓存中int num = stockDao.findById(productid);if (num > 0) {//修改库存---incr---定时器[redis  数据库同步]stockDao.update(productid);System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个");return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个";} else {System.out.println("商品编号为:" + productid + "的商品库存不足。");return "商品编号为:" + productid + "的商品库存不足。";}}finally {lock.unlock();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1488297.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

从0到1:理发店预约剪发小程序开发笔记(上)

背景 理发师可以在小程序上设置自己的可预约时间&#xff0c;价格&#xff0c;自我介绍&#xff0c;顾客可以根据理发师的日程安排选择合适的时间进行预约和支付。这样可以提高预约的效率&#xff0c;减少沟通成本&#xff0c;方便双方的安排。 功能规划 首页展示&#xff1…

【CPS出版】2024年智能计算与数据分析国际学术会议(ICDA 2024,9月6日-8)

为探讨数据科学和计算智能领域的关键问题&#xff0c;促进相关交流&#xff0c;2024年智能计算与数据分析国际学术会议&#xff08;ICDA 2024)将于2024年9月6日-8日在中国青岛召开。 本届会议拟邀请数据分析和计算智能领域的顶级专家、学者和产业界优秀人才&#xff0c;围绕当前…

【音视频之SDL2】bmp图片与绘制bmp

文章目录 前言BMP是什么SDL2绘制BMP的原理SDL2绘制BMP的流程SDL_LoadBMP作用函数原型参数返回值示例代码 SDL_BlitSurface作用函数原型参数返回值 示例代码效果展示总结 前言 在现代多媒体应用中&#xff0c;图像的处理和显示是非常重要的一部分。无论是在游戏开发还是在视频处…

腾讯QQ临时对话框功能取消免费使用,替代的是腾讯推出的“企点客通”模块实现,买通服务即可实现

最近遇到一个项目有这么一个业务&#xff1a; 要实现的功能是&#xff1a;QQ在线咨询 想要实现的效果如图所示&#xff1a; 按照以往的开发经验使用的是直接使用以下代码&#xff1a; <a target"_blank" href"tencent://message/?uin2104*****57(QQ号)&am…

HTML常用的转义字符——怎么在网页中写“<div></div>”?

一、问题描述 如果需要在网页中写“<div></div>”怎么办呢&#xff1f; 使用转义字符 如果直接写“<div></div>”&#xff0c;编译器会把它翻译为块&#xff0c;类似的&#xff0c;其他的标签也是如此&#xff0c;所以如果要在网页中写类似于“<div…

CDGA|数据治理:安全如何贯穿数据供给、流通、使用全过程

随着信息技术的飞速发展&#xff0c;数据已经成为企业运营、社会管理和经济发展的核心要素。然而&#xff0c;数据在带来巨大价值的同时&#xff0c;也伴随着诸多安全风险。因此&#xff0c;数据治理的重要性日益凸显&#xff0c;它不仅仅是对数据的简单管理&#xff0c;更是确…

懒人精灵安卓版纯本地离线文字识别插件

目的 懒人精灵是一款可以模拟鼠标和键盘操作的自动化工具。它可以帮助用户自动完成一些重复的、繁琐的任务&#xff0c;节省大量人工操作的时间。懒人精灵也包含图色功能&#xff0c;识别屏幕上的图像&#xff0c;根据图像的变化自动执行相应的操作。本篇文章主要讲解下更优秀的…

反激Flyback从逆向到初步设计(UC2844)

一.Flyback基本拓扑 国标gb/t 12325-2008《电能质量供电电压偏差》规定&#xff1a;220v单向供电电压偏差为标称电压的-10%&#xff0c;7%。 对应220V的标称电压&#xff0c;其浮动范围是在198~235.4V。以下运算均基于此规定进行。 首先220V进入EMI模块&#xff0c;消除差模干扰…

MySQL练习05

题目 步骤 触发器 use mydb16_trigger; #使用数据库create table goods( gid char(8) primary key, name varchar(10), price decimal(8,2), num int);create table orders( oid int primary key auto_increment, gid char(10) not null, name varchar(10), price decima…

Zookeeper入门篇,了解ZK存储特点

Zookeeper入门篇&#xff0c;了解ZK存储特点 前言一、为什么要用 Zookeeper&#xff1f;二、Zookeeper存储特色1. 树状结构2. 节点类型 三、存储位置1. 内存存储1. DataTree2. DataNode 2. 硬盘存储1. 事务日志2. 快照 前言 继上次说完 Zookeeper 的安装后&#xff0c;已经过去…

数据分析或处理中关于坐标系的一些事

通过对本文的阅读&#xff0c;你将获取坐标系的一些基础知识&#xff0c;以及学会如何使用pyproj实现地理数据的投影与转换。更重要的是&#xff0c;作为一个开发者&#xff0c;面对地理坐标系的图层数据&#xff0c;需要进行面积计算、距离量测、规则分块等需求时&#xff0c;…

海山数据库(He3DB)源码解读:海山PG 死锁处理实现

目录 背景 整体概述 数据结构 死锁处理设计 设计原理 主要流程 主要接口 作者介绍 背景 He3DB for PostgreSQL是受Aurora论文启发&#xff0c;基于开源数据库PostgreSQL 改造的数据库产品。架构上实现计算存储分离&#xff0c;并进一步支持数据的冷热分层&#xff0c;大幅…

音视频开发之旅(85)- 图像分类-VGG模型解析

目录 1. VGG解决的问题 2. 网络结构和参数 3. pytorch搭建vgg 4.flower_photos分类任务实践 5.资料 一、VGG解决的问题 论文链接&#xff1a;https://arxiv.org/pdf/1409.1556 在VGG之前&#xff0c;大多数深度学习模型相对较浅&#xff0c;比如下面的AlexNet(5层卷积和3…

网络服务与应用

一、 文件传输 FTP 1、FTP采用典型的C/S架构&#xff08;即服务器端和客户端模型&#xff09;&#xff0c;客户端与服务器端建立TCP连接之后即可实现文件的上传、下载。 2、FTP传输过程 1&#xff09;、主动模式&#xff08;POST&#xff09;&#xff1a;入站连接 2&#x…

微服务实践和总结

H5原生组件web Component Web Component 是一种用于构建可复用用户界面组件的技术&#xff0c;开发者可以创建自定义的 HTML 标签&#xff0c;并将其封装为包含逻辑和样式的独立组件&#xff0c;从而在任何 Web 应用中重复使用。 <!DOCTYPE html> <html><head…

企业利用AI智能名片S2B2C商城小程序参与社区团购的风险与机遇分析

摘要 在新零售浪潮的推动下&#xff0c;社区团购以其独特的商业模式迅速崛起&#xff0c;成为连接消费者与供应商的重要桥梁。企业纷纷探索如何有效利用这一新兴渠道&#xff0c;以扩大市场份额、提升品牌影响力。AI智能名片S2B2C商城小程序的引入&#xff0c;为企业参与社区团…

AWS Route 53:一站式域名注册与DNS管理解决方案

在构建网络应用时&#xff0c;域名注册是不可或缺的一步。作为全球领先的云服务提供商&#xff0c;Amazon Web Services (AWS) 不仅提供强大的云计算资源&#xff0c;还通过其服务 Route 53 提供域名注册功能。本文中九河云将详细介绍 AWS 的域名注册服务&#xff0c;以及它如何…

视频生成AI工具——PixVerse V2 登场:支持一键生成5段、最长 40S 连续视频!

就在昨天&#xff0c;光源伙伴 「 爱诗科技 」正式发布其视频生成产品 PixVerse V2 , 并全球同步开放&#xff0c;更低门槛&#xff0c;更高质量&#xff0c;更有逻辑&#xff0c;更长时长&#xff0c;这几个“更”&#xff0c;让这款产品受到了超高关注&#xff0c;今天带大家…

PHP基础语法-Part1

脚本格式 PHP脚本以<?php开头&#xff0c;以?>结尾&#xff1b; PHP语句以分号结尾&#xff08;;&#xff09; PHP是解释型语言&#xff1b; 输入和输出 获取用户的输入&#xff1a; $input readline("input:"); echo $input; echo "input:";…

自定义 RAG 工作流:在 IDE 中结合 RAG 编排,构建可信的编码智能体

构建编码智能体并非一件容易的事。结合我们在 AutoDev、ArchGuard Co-mate、ChocoBuilder 等智能体项目的经验&#xff0c;我们开始思考在 Shire 语言中提供一种新的 RAG 工作流。结合我们先前构建的 IDE 基础设施&#xff08;代码生成、代码校验、代码执行等接口&#xff09;&…