SpringBoot整合Redis入门之缓存数据的方法


Posted in Redis onNovember 17, 2021

前言

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。

为什么要使用Redis呢?

举个例子,假如系统中有2千万用户信息,用户信息基本固定,一旦录入很少变动,那么你每次加载所有用户信息时,如果都要请求数据库,数据库编译并执行你的查询语句,这样效率就会低下很多,针对这种信息不经常变动并且数据量。

较大的情况,通常做法,就是把他加入缓存,每次取数前先去判断,如果缓存不为空,那么就从缓存取值,如果为空,再去请求数据库,并将数据加入缓存,这样大大提高系统访问效率。


相关依赖

<!-- springboot版本 -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.7.RELEASE</version>
</parent>
<!-- 依赖 -->
<dependencies>
	<!-- redis -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-redis</artifactId>
	</dependency>
	<!-- 通用池 -->
	<dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-pool2</artifactId>
	</dependency>
	<!-- mysql -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
	</dependency>
	<!-- mybatis -->
		<dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>2.1.1</version>
	</dependency>
	<!-- 通用mapper -->
	<dependency>
		<groupId>tk.mybatis</groupId>
		<artifactId>mapper-spring-boot-starter</artifactId>
		<version>2.1.5</version>
	</dependency>
	<!-- lombok -->
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
	</dependency>
	<!-- test -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
	</dependency>
</dependencies>

配置

# 端口
server:
  port: 9998
# mysql数据源
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/dbtest?serverTimezone=GMT%2B8
# redis
  redis:
    host: localhost
    port: 6379
    timeout: 1000
    jedis:
      pool:
        min-idle: 5
        max-idle: 10
        max-wait: -1
# mybatis
mybatis:
  mapper-locations: classpath:/mybatis/mapper/*.xml
  type-aliases-package: cn.kgc.entities
#  开启驼峰命名
  configuration:
    map-underscore-to-camel-case: true
# log
logging:
  level:
    cn.kgc: debug

数据库

SpringBoot整合Redis入门之缓存数据的方法

#建表
CREATE TABLE `emp`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
#插入数据
INSERT INTO `emp` VALUES (1, '张三', 18);
INSERT INTO `emp` VALUES (2, '李四', 20);
INSERT INTO `emp` VALUES (3, '王五', 22);

实体类

Emp

@Data
@Table(name = "emp")
public class Emp implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private Integer age;
}

RedisConfig

指定Redis序列化方式

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);

        // 指定kv的序列化方式
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setKeySerializer(new StringRedisSerializer());

        return redisTemplate;
    }
}

Mapper

Emp的Mapper接口继承tk的Mapper类,泛型为实体类Emp

public interface EmpMapper extends Mapper<Emp> {

}

Service接口

业务接口定义add添加和getEmpById根据id查询的方法

public interface EmpService {
    public void add(Emp emp);
    public Object getEmpById(Integer id);
}

Service实现类

先查Redis,Redis没有数据再从数据库中拿数据,同时缓存到Redis中。

@Service
@Slf4j
public class EmpServiceImpl implements EmpService {

    @Autowired
    public RedisTemplate redisTemplate;

    @Resource
    private EmpMapper empMapper;

    @Override
    public void add(Emp emp) {
        empMapper.insert(emp);
    }

    @Override
    public  Object getEmpById(Integer id) {
        // 先从缓存获取数据,如果有则直接返回
        //                   如果无,则查询mysql,并将数据设置到缓存
        String key = "user:" + id;
        Object userObj = redisTemplate.opsForValue().get(key);
        if(userObj == null){
            synchronized (this.getClass()){
                userObj = redisTemplate.opsForValue().get(key);
                if(userObj == null ){
                    log.debug("----> 查询数据库..............");
                    // 查数据库
                    Emp emp = empMapper.selectByPrimaryKey(id);
                    redisTemplate.opsForValue().set(key,emp);
                    return emp;
                }else{
                    log.debug("----> 查询缓存(同步代码块)>>>>>>>>>>>>>>>>>");
                    return userObj;
                }
            }

        }else{
            log.debug("----> 查询缓存>>>>>>>>>>>>>>>>>");
        }
        return userObj;
    }
}

测试Redis

Redis-Controller

@RestController
public class RedisContoller {
    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/redis/get/{key}")
    public Object get(@PathVariable("key") String key){
       return  redisTemplate.opsForValue().get(key);
    }

    @PostMapping("/redis/set/{key}/{value}")
    public Object set(@PathVariable("key") String key,
                      @PathVariable("value") String value){
        redisTemplate.opsForValue().set(key,value);
        return "set success";
    }
}

Controller

Redis+MySQL

@RestController
public class EmpController {
    @Autowired
    private EmpService empService;

    @PostMapping("/emp")
    public String addEmp(Emp emp){
        empService.add(emp);
        return "add ok";
    }

    @GetMapping("/emp/{id}")
    public Object getEmpById(@PathVariable("id") Integer id){
        ExecutorService es = Executors.newFixedThreadPool(200);
        for(int i=0 ;i<500;i++){
            es.submit(new Runnable() {
                @Override
                public void run() {
                    empService.getEmpById(id);
                }
            });
        }
        return empService.getEmpById(id);
    }
}

到此这篇关于SpringBoot整合Redis入门之缓存数据的文章就介绍到这了,更多相关SpringBoot整合Redis缓存数据内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
Redis 哨兵集群的实现
Jun 18 Redis
Redis基于Bitmap实现用户签到功能
Jun 20 Redis
压缩Redis里的字符串大对象操作
Jun 23 Redis
Redis Cluster集群动态扩容的实现
Jul 15 Redis
解析redis hash应用场景和常用命令
Aug 04 Redis
Redis Stream类型的使用详解
Nov 11 Redis
Spring Boot实战解决高并发数据入库之 Redis 缓存+MySQL 批量入库问题
Feb 12 Redis
Redis 的查询很快的原因解析及Redis 如何保证查询的高效
Mar 16 Redis
浅谈Redis的事件驱动模型
May 30 Redis
Redis实现主从复制方式(Master&Slave)
Jun 21 Redis
Redis+AOP+自定义注解实现限流
Jun 28 Redis
Redis主从复制操作和配置详情
Sep 23 Redis
Window server中安装Redis的超详细教程
关于SpringBoot 使用 Redis 分布式锁解决并发问题
Redis Stream类型的使用详解
Redis 持久化 RDB 与 AOF的执行过程
Redis模仿手机验证码发送的实现示例
redis中lua脚本使用教程
Redis高并发防止秒杀超卖实战源码解决方案
You might like
PHP-MySQL教程归纳总结
2008/06/07 PHP
PHPMailer邮件发送的实现代码
2013/05/04 PHP
PHP实现的基于单向链表解决约瑟夫环问题示例
2017/09/30 PHP
PHP设计模式(七)组合模式Composite实例详解【结构型】
2020/05/02 PHP
jquery实现盒子下拉效果示例代码
2013/09/12 Javascript
JavaScript计划任务后台运行的方法
2015/12/18 Javascript
利用Chrome DevTools直接调试Node.js和JavaScript的方法详解(并行)
2017/02/16 Javascript
jquery实现折叠菜单效果【推荐】
2017/03/08 Javascript
AngularJS实现的回到顶部指令功能实例
2017/05/17 Javascript
前端把html表格生成为excel表格的实例
2017/09/19 Javascript
node.js学习之断言assert的使用示例
2017/09/28 Javascript
input 标签实现输入框带提示文字效果(两种方法)
2017/10/09 Javascript
使用3D引擎threeJS实现星空粒子移动效果
2020/09/13 Javascript
Vue的事件响应式进度条组件实例详解
2018/02/04 Javascript
[05:15]2018年度CS GO社区贡献奖-完美盛典
2018/12/16 DOTA
python 随机数生成的代码的详细分析
2011/05/15 Python
python绘图库Matplotlib的安装
2014/07/03 Python
python字符串对其居中显示的方法
2015/07/11 Python
Python+Selenium自动化实现分页(pagination)处理
2017/03/31 Python
Python实现读取SQLServer数据并插入到MongoDB数据库的方法示例
2018/06/09 Python
Python爬取商家联系电话以及各种数据的方法
2018/11/10 Python
Python3+Appium安装使用教程
2019/07/05 Python
Python Selenium 设置元素等待的三种方式
2020/03/18 Python
Python基于pyjnius库实现访问java类
2020/07/31 Python
python pyg2plot的原理知识点总结
2021/02/28 Python
CSS3 Media Queries详细介绍和使用实例
2014/05/08 HTML / CSS
无需JS和jQuery代码实现CSS3鼠标浮动放大图片
2016/11/21 HTML / CSS
canvas绘图按照contain或者cover方式适配并居中显示
2019/02/18 HTML / CSS
N.Peal官网:来自伦敦的高档羊绒品牌
2018/10/29 全球购物
struct与class的区别
2014/02/03 面试题
关于递归的一道.NET面试题
2013/05/12 面试题
高中生毕业自我鉴定范文
2013/12/22 职场文书
劳动仲裁代理词范文
2015/05/25 职场文书
公文写作指导之倡议书!
2019/07/03 职场文书
关于考试抄袭的检讨书
2019/11/02 职场文书
Python基本知识点总结
2022/04/07 Python