首页 > 数据库 >Redis缓存优化项目

Redis缓存优化项目

时间:2024-01-25 20:24:53浏览次数:35  
标签:缓存 Redis redis user 优化 public redisTemplate

Redis数据库基础

Redis数据库概述

Redis是一个基于内存的key-value结构数据库,即非关系型数据库

(NoSql)数据库并不是要取代关系型数据库,而是关系型数据库的一种补充。

Redis是互联网技术领域使用最为广泛的存储中间件,他是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据可以达到100000+的QPS(每秒内查询次数)

主要特点

  • 基于内存存储,读写性能高
  • 适合存储热点数据
  • 企业应用广泛

Redis下载与开启服务

下载

Redis的Windows是绿色软件,在官网下载之后,之间解压即可使用

注意其中的一些目录结构

redis.windows.conf Redis配置文件

redis-cli.exe Redis客户端

redis-server.exe Redis服务器

开启服务

Window版Redis启动命令

cmd命令窗口启动命令

redis-server.exe  redis.windows.conf

也可以使用脚本命令

start cmd /k "redis-server.exe redis.windows.conf"

建立bat后缀文件放入文件位置,即可开启服务

Redis文件配置

在redis.windows.conf文件为redis的核心配置文件,可根据项目情况设置不同的参数

  • 设置Redis服务密码,添加内容为 requirepass 123456
  • 设置密码为123456.

客户端图形工具

我们通常使用Redis客户端图形工具,因为默认提供的客户端连接工具界面不太友好,同时操作也比较麻烦

我在项目中使用的是Another Redis Desktop Manager

Redis数据类型和命令

Redis数据类型

  • 字符串(String),普通字符串,Redis中最简单的数据类型
  • 哈希(hash),也叫散列,类似于Java中的HashMap结构
  • 列表(list),按照插入顺序排序,可以重复元素,类似Java中的HashSet
  • 集合(set),无序集合,没有重复元素,类似JavaHashSet
  • 有序集合,集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素

Redis在Java中操作

我们在Java中操作Redis

Spring对Redis客户端进行了整合,提供了Spring Data Redis ,在SpringBoot项目中还提供了对应的Starter,即spring-boot-starter-data-redis

Spring Data Redis

Spring Data Redis是Spring中的一部分,提供了在Spring应用中,通过简单的配置就可以访问Redis服务,对Redis底层开发包进行了高度封装。

可以使用Spring Data Redis来简化Redis操作

Spring Boot中提供了对应的Starter,maven坐标:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

在Spring Data Redis中提供了一个高度封装的类,RedisTemplate,对相应的ap进行了封装,将同一类型的操作封装成operation接口,具体分类如下:

  • ValueOperations: string数据操作
  • SetOperations: set类型数据操作
  • ZSetOperations: zet 类型数据操作
  • HashOperations: hash类型的数据操作
  • ListOperations: list类型的数据操作

在application.yml文件中,配置redis连接

spring:
  redis:
    host: localhost
    port: 6379
    password: 123456

在以上环境搭建之后,springboot框架会自动装配RedisTemplate,我们就可以在任意的位置使用这个对象

测试

下面我们来简单的新建一个测试类,并集成springboot,并且调用RedisTemplate

package com.itheima.test;

import com.itheima.CacheDemoApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = CacheDemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisTest {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Test
    public void test(){
        System.out.println(redisTemplate);
    }
    
}

在上面测试案例中,我们直接注入了RedisTemplate,并且指定了泛型为String

  • 如果不指定泛型也可以进行操作,但是存储对象的时候需要进行序列化
  • 一般项目中存储对象都会转化为json字符串,在进行存储,所以一般会选择使用泛型为String ,避免大量的序列化操作

操作字符串数据类型

/**
 * 操作字符串类型的数据
 */
@Test
public void testString(){
    // set get setex setnx
    redisTemplate.opsForValue().set("name","小明");
    
    String name = redisTemplate.opsForValue().get("name");
    
    System.out.println(name);
    
    redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);
    redisTemplate.opsForValue().setIfAbsent("lock","1");
    redisTemplate.opsForValue().setIfAbsent("lock","2");
}

操作哈希数据类型

/**
 * 操作哈希类型的数据
 */
@Test
public void testHash(){
    //hset hget hdel hkeys hvals
    redisTemplate.opsForHash().put("heima","name","tom");
    redisTemplate.opsForHash().put("heima","age","20");
    String name = (String) redisTemplate.opsForHash().get("heima", "name");
    System.out.println(name);

    Set keys = redisTemplate.opsForHash().keys("heima");
    System.out.println(keys);

    List values = redisTemplate.opsForHash().values("heima");
    System.out.println(values);

    redisTemplate.opsForHash().delete("heima","age");
}

操作列表数据类型

/**
 * 操作列表类型的数据
 */
@Test
public void testList(){
    //lpush lrange rpop llen
    redisTemplate.opsForList().leftPushAll("mylist","a","b","c");
    redisTemplate.opsForList().leftPush("mylist","d");

    List mylist = redisTemplate.opsForList().range("mylist", 0, -1);
    System.out.println(mylist);

    redisTemplate.opsForList().rightPop("mylist");

    Long size = redisTemplate.opsForList().size("mylist");
    System.out.println(size);
}

操作集合类型数据

/**
 * 操作集合类型的数据
 */
@Test
public void testSet(){
    //sadd smembers scard sinter sunion srem
    redisTemplate.opsForSet().add("set1","a","b","c","d");
    redisTemplate.opsForSet().add("set2","a","b","x","y");

    Set members = redisTemplate.opsForSet().members("set1");
    System.out.println(members);

    Long size = redisTemplate.opsForSet().size("set1");
    System.out.println(size);

    Set intersect = redisTemplate.opsForSet().intersect("set1", "set2");
    System.out.println(intersect);

    Set union = redisTemplate.opsForSet().union("set1", "set2");
    System.out.println(union);

    redisTemplate.opsForSet().remove("set1","a","b");
}

操作有序集合类型数据

/**
 * 操作有序集合类型的数据
 */
@Test
public void testZset(){
    //zadd zrange zincrby zrem
    redisTemplate.opsForZSet().add("zset1","a",10);
    redisTemplate.opsForZSet().add("zset1","b",12);
    redisTemplate.opsForZSet().add("zset1","c",9);

    Set zset1 = redisTemplate.opsForZSet().range("zset1", 0, -1);
    System.out.println(zset1);

    redisTemplate.opsForZSet().incrementScore("zset1","c",10);

    redisTemplate.opsForZSet().remove("zset1","a","b");
}

缓存框架--Spring Cache

在项目中,我们一般统一管理缓存的框架来实现缓存优化,主要原因是耦合度更低,切换缓存的成本较低

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单的加一个注解,就能实现缓存功能

导入Redis和SpringCache依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

添加配置支持

application.yml文件中添加redis的支持

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456

在SpringCache中提供了很多缓存操作的注解

注解 说明
@EnableCaching 开启缓存注解功能吗,通常加在启动类上
@Cacheable 在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据,如果没有缓存数据,调用方法并将方法返回值放到缓存中
@CachePut 将方法的返回值放到缓存中
@CacheEvict 将一条或多条数据从缓存中删除
@Caching 缓存的结合体,可以组合以上注解在一个方法中使用,比如有新增有删除

在方法执行前,spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中,查询的时候使用

@Cacheable(cacheNames = "userCache",key="#id")
public User getById(Long id){
    User user = userMapper.getById(id);
    if(user == null){
        throw new RuntimeException("用户不存在");
    }
    return user;
}

多条件查询使用Cacheable,比如查询的方法参数有多个,我们可以使用hashcode作为缓存的key,

@Cacheable(value = "userCache",key="#userDto.hashCode()",unless = "#result.size() == 0")
public List<User> getList(UserDto userDto){
    List<User> list = userMapper.getList("%" + userDto.getName() + "%", userDto.getAge());
    return list;
}

需要提供一个hashCode方法

@Data
public class UserDto {

    private String name;
    private int age;

    @Override
    public int hashCode() {
        int result = Objects.hash(getName(),getAge());
        return result;
    }
}

hashcode的特点是,只要参数相同,则生成后的hashcode值肯定相同

如果返回结果为空,则不缓存unless="#result == null"或unless="#result.size()==0"

@CachePut

作用: 将方法返回值,放入缓存,一般保存的时候使用该注解

@CachePut(value = "userCache", key = "#user.id")//key的生成:userCache::1
public User insert(User user){
    userMapper.insert(user);
    return user;
}
  • #user.id : #user指的是方法形参的名称, id指的是user的id属性 , 也就是使用user的id属性作为key

@CacheEvict

作用: 清理指定缓存

@CacheEvict(cacheNames = "userCache",key = "#id")//删除某个key对应的缓存数据
public void deleteById(Long id){
    userMapper.deleteById(id);
}

@CacheEvict(cacheNames = "userCache",allEntries = true)//删除userCache下所有的缓存数据
public void deleteAll(){
    userMapper.deleteAll();
}

@Caching

作用: 组装其他缓存注解

  • cacheable 组装一个或多个@Cacheable注解
  • put 组装一个或多个@CachePut注解
  • evict 组装一个或多个@CacheEvict注解
@Caching(
         cacheable = {
                 @Cacheable(value = "userCache",key = "#id")
         },
         put = {
                 @CachePut(value = "userCache",key = "#result.name"),
                 @CachePut(value = "userCache",key = "#result.age")
         }
 )
 public User insert(User user){
     userMapper.insert(user);
     return user;
 }
```****

标签:缓存,Redis,redis,user,优化,public,redisTemplate
From: https://www.cnblogs.com/yifan0820/p/17988077

相关文章

  • C#对象二进制序列化优化:从位域技术优化压缩数据大小
    目录1.引言2.优化过程2.1.进程对象定义与初步分析2.2.排除Json序列化2.3.使用BinaryWriter进行二进制序列化2.4.数据类型调整2.5.再次数据类型调整与位域优化3.优化效果与总结 1.引言在操作系统中,进程信息对于系统监控和性能分析至关重要。假设我们......
  • Legacy (线段树优化建图)
    题目链接:Legacy-洛谷|计算机科学教育新生态(luogu.com.cn)题解:考虑题目中一个点向区间连边,如真的对区间中的每一点分别连边后跑最短路,时间空间都要炸。因为是一个点向区间连边,考虑线段树。1到n构造两颗区间线段数 观察上图(从网上搬的)两颗线段树,一颗入树父亲向儿子连......
  • Redis篇-redis使用场景-缓存-缓存雪崩-04
    1缓存雪崩缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。解决方案:给不同Key的TTL添加随机值;利用Redis集群提高服务的可用性;哨兵模式、集群模式给缓存业务添加降级限流策略;ngxin或springcloudGateway给业务添加......
  • MySQL SQL点查,范围查,排序,分组的Explain分析和SQL优化(8.0版本)
    MySQLSQL常用优化主要有where,range,order,groupby,or等查询。下图是优化的原则,后面会有一个例子来看看:比如建立了联合索引(c1,c2,c3),索引长度分别为5,5,4。数据有50条:点查SELECT*FROMtraining.t1wherec3=1andc2=1andc1=1;使用了索引,只要全部包含索引列,那么点查顺序......
  • Web前端性能优化
    性能优化是前端开发无法避免的点,给客户带去良好的访问体验也是开发人员必须关注的问题。前端性能优化大体分为两个部分:代码优化、资源及其他优化,本文主要记录资源及其他优化要怎么做。1、CSS样式文件在页面头部引入,Javascript文件在页面尾部引入页面加载单线程可能会阻塞页面的......
  • go-zero配置DB的redis缓存
    配置定义:#catinternal/config/config.gopackageconfigimport( "github.com/zeromicro/go-zero/rest" "github.com/zeromicro/go-zero/core/stores/cache")typeConfigstruct{ rest.RestConf CacheRediscache.CacheConf}对应的配置文件:#cat......
  • 量化交易中组合优化的那些事儿
    简介组合优化,本质上是LP和QP的凸优化问题,设定多个交易约束,最大化某一目标函数。/n比如:非空约束下,求解资产占比,使得给定风险下,收益最大化或者同收益情况下,风险最小化。方法论确定目标函数确定约束算法求解拓展不同的应用场景,不同的侧重点,我们可以建立不同的优化目标和约......
  • Redis实战篇
    实战篇Redis优秀博客黑马点评项目学习笔记(15w字详解,堪称史上最详细,欢迎收藏)-CSDN博客Redis实战篇|Kyle'sBlog(cyborg2077.github.io)开篇导读hutol工具使用对象bean和JsonStr互转//功能:javabean转jsonstr用途:存入到redisStringjsonstr=JSONUtil.toJsonSt......
  • 神经网络优化篇:详解为超参数选择合适的范围(Using an appropriate scale to pick hyper
    为超参数选择合适的范围假设要选取隐藏单元的数量\(n^{[l]}\),假设,选取的取值范围是从50到100中某点,这种情况下,看到这条从50-100的数轴,可以随机在其取点,这是一个搜索特定超参数的很直观的方式。或者,如果要选取神经网络的层数,称之为字母\(L\),也许会选择层数为2到4中的某个值,接着顺......
  • 界面组件DevExpress .NET MAUI中文教程 - 如何优化手机屏幕空间?
    DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpressDashboardeXpressApp框架、适用于VisualStudio的CodeRush等一系列辅助工具。获取DevExpressv23.2正式版下载DevExpress技术交流群9:909157416      欢迎一起进群讨论BottomSheet......