Redis学习记录

Redis安装

首先是Redis的下载地址,事实上,Redis已经出到7的版本了,我们这里使用的是5的版本。(3也能用)

Redis下载地址

我们将Redis下载下来并解压:

在这里插入图片描述
我们如何启动呢?

redis-server.exe redis.windows.conf

使用客户端连接redis:

redis-cli.exe

当然,我们还可以连接其他主机上的redis数据库

redis-cli.exe -h localhost -p 6379

在这里插入图片描述

随后,我们想到,Redis作为一种数据库,为何没有像MySQL一样指定用户名与密码呢,事实上,Redis是没有用户的,只需要指定密码即可,而默认的redis是不指定密码的,因此我们可以自己设置一下,打开redis.windows.conf文件,搜索pass,大约在502行,有段代码:#requirepass foobared,将前面的#号取消,后面将foobared改为我们设置的密码即可,如下:

在这里插入图片描述

随后我们将Redis的服务关闭,随后再次输入先前的连接命令,发现需要认证。

在这里插入图片描述
随后在先前的命令后加上认证用户的密码即可。

redis-cli.exe -h localhost -p 6379 -a 123456

此时我们发现,我们每次使用这个命令行来操作redis很不方便,因此我们最终选择使用一个图形化界面Another Redis Desktop Manager来操作redis。

在这里插入图片描述

安装成功后点击新建链接,我们输入下面的内容:

在这里插入图片描述
随后我们就可以看到redis目前的使用情况了:

在这里插入图片描述

Redis中的数据类型

Redis是一种基于内存的Key-Value结构型数据库,其特点与应用场景如下:

  • 基于内存存储,读写性能高
  • 适合存储热点数据(热点商品、资讯、新闻)

Rediskey是一种字符串类型,而value的基本数据类型则为以下几种:

  • 字符串 string
  • 哈希 hash
  • 列表 list
  • 集合 set
  • 有序集合 sorted set/zset

下面对这五种数据类型的特点以及所适合的应用场景进行介绍:

字符串(string):普通字符串,Redis中最简单的数据类型
哈希(hash):也叫散列,类似于Java中的HashMap结构,它包含一个域与一个值,用于存储对象比较合适
列表(list):按照插入顺序排序,可以有重复元素,类似于Java中的LinkedList,如朋友圈点赞顺序
集合(set):无序集合,没有重复元素,类似于Java中的Hashset,朋友圈交叉,求交集
有序集合(sorted set/zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素,,排行榜

常用命令

Redis 字符串类型常用命令:

命令格式作用
SET key value设置指定key的傎
GET key获取指定key的值
SETEX key seconds value设置指定key的值,并将 key 的过期时间设为 seconds 秒(生成验证码)
SETNX key value只有在 key 不存在时设置 key 的值(分布式锁)

直接在Redis的图形界面中操作即可。

字符串常用命令

在这里插入图片描述

哈希操作常用命令

Redis hash 是一个string类型的 field 和 value 的映射表,hash特别适合用于存储对象,常用命令:

命令含义
HSET key field value将哈希表 key 中的字段 field 的值设为 value
HGET key field获取存储在哈希表中指定字段的值
HDEL key field删除存储在哈希表中的指定字段
HKEYS key获取哈希表中所有字段
HVALS key (VALS代表Values)获取哈希表中所有值,通过key获取value,这个value是第二级value值

在这里插入图片描述

在这里插入图片描述

列表操作命令

Redis 列表是简单的字符串列表,按照插入顺序排序,常用命令:

命令含义
LPUSH key value1 [value2]将一个或多个值插入到列表头部,这里的L不是List而是Left
LRANGE key start stop获取列表指定范围内的元素
RPOP key移除并获取列表最后一个元素
LLEN key获取列表长度

在这里插入图片描述

在这里插入图片描述

集合操作命令

Redis set 是string类型的无序集合。集合成员是唯一的,集合中不能出现重复的数据,常用命令:

命令含义
SADD key member1 [member2]向集合添加一个或多个成员
SMEMBERS key返回集合中的所有成员(members)
SCARD key获取集合的成员数
SINTER key1 [key2]返回给定所有集合的交集
SUNION key1 [key2]返回所有给定集合的并集
SREM key member1 [member2]删除集合中一个或多个成员

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

有序集合操作命令

Redis有序集合是string类型元素的集合,且不允许有重复成员。每个元素都会关联一个double类型的分数。常用命令:

命令含义
ZADD key score1 member1 [score2 member2]向有序集合添加一个或多个成员
ZRANGE key start stop [WITHSCORES]通过索引区间返回有序集合中指定区间内的成员
ZINCRBY key increment member有序集合中对指定成员的分数加上增量increment (增加increase)
ZREM key member [member …]移除有序集合中的一个或多个成员

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

通用命令操作

Redis的通用命令是不分数据类型的,都可以使用的命令

命令含义
KEYS pattern查找所有符合给定模式( pattern)的 key
EXISTS key检查给定 key 是否存在
TYPE key返回 key 所储存的值的类型
DEL key该命令用于在 key 存在是删除 key

Redis在Java中的使用

RedisJava 客户端很多,常用的几种:

  • eJedis:官方指定,命令和Redis的命令相同
  • Lettuce:性能好
  • Spring Data Redis:Spring Data Redis 是Spring的一部分,对 Redis 底层开发包进行了高度封装。
    在 Spring 项目中,可以使用Spring Data pedis来简化操作

由于我们使用的是Spring框架,因此我们选用Spring Data Redis来进行操作,其操作遵循下面几个步骤:

  1. 导入Spring Data Redismaven坐标
  2. 配置Redis数据源
  3. 编写配置类,创建RedisTemplate对象
  4. 通过RedisTemplate对象操作Redis

导入Spring Data Redismaven坐标

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

配置Redis数据源,其与配置mysql的datasource是平级的

sky:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    database: 10

这里需要注意database: 10的含义,代表使用第11个数据库,当然这个可以不配置,默认为0
在这里插入图片描述

编写配置类,创建RedisTemplate对象,加入@Configuration注解,会在服务启动时加载

package com.sky.config;

import org.springframework.data.redis.connection.RedisConnectionFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@Slf4j
public class RedisConfiguration {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        log.info("开始创建redis模板对象...");

        RedisTemplate redisTemplate = new RedisTemplate();
        //设置redis的连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //设置redis key的序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

那么如何使用呢?针对Redis的五种数据类型,Spring封装了不同的接口:

package com.sky.test;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;

import java.util.concurrent.TimeUnit;

@SpringBootTest
public class SpingBootRedisTest {

    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void test(){
        System.out.println(redisTemplate);
        //针对Redis常用的五种数据类型,Spring分别封装了对应的接口用于操作各个数据类型
        //操作String类型
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //操作hash类型
        HashOperations hashOperations = redisTemplate.opsForHash();
        //操作List列表类型
        ListOperations listOperations = redisTemplate.opsForList();
        //操作集合类型
        SetOperations setOperations = redisTemplate.opsForSet();
        //操作有序集合类型
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();

    }
    
}

测试String类型

 	@Test
    public void testString(){
       //set get setex setnx
        redisTemplate.opsForValue().set("name","鹏翔");
        //获取set
        String name= (String) redisTemplate.opsForValue().get("name");
        //setex 设置时间
        redisTemplate.opsForValue().set("code","1234",10, TimeUnit.MINUTES);
        //setnx 不存在则创建
        redisTemplate.opsForValue().setIfAbsent("lock","1");
        redisTemplate.opsForValue().setIfAbsent("lock","2");//
    }

我们选用的数据库是10号,查看一下,刚刚的数据已经插入成功了,但我们发现key没有问题,但value无论是英文还是中文都貌似出现了乱码,事实上其并不是乱码,而是由于我们在使用Java对Redis进行操作时对Value进行了序列化,事实上我们的key原本也是要进行序列化的,但我们在配置时给设置了String类型的序列化,因此就没有问题了,而Value的类型是不确定的,因此不能指定。

//设置redis key的序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());

在这里插入图片描述
如果不对Key进行String序列化,则会调用默认的序列化器,结果便是下面这样:

在这里插入图片描述

测试Hash类型

 	@Test
    public void testhash(){
        //hset hget hdel hkeys hvals
        HashOperations hashOperations = redisTemplate.opsForHash();
        hashOperations.put("person1","name","鹏翔");
        hashOperations.put("person1","age","18");
        String o = (String) hashOperations.get("person1", "name");
        System.out.println(o);
        Set keys = hashOperations.keys("person1");
        System.out.println(keys);
        List values = hashOperations.values("person1");
        System.out.println(values);
        hashOperations.delete("person1","age");
    }

结果如下:

在这里插入图片描述

在这里插入图片描述

测试List类型

 @Test
    public void testList(){
        ListOperations listOperations = redisTemplate.opsForList();
        //lpush lrange rpop llen
        //pushAll可以插入一个或多个
        listOperations.leftPushAll("mylist","a","b","c","d");
        //push只能插入一个
        listOperations.leftPushAll("mylist","e");
        //读取List
        List mylist = listOperations.range("mylist", 0, -1);
        System.out.println(mylist);
        //获取List的大小
        Long size = listOperations.size("mylist");
        System.out.println(size);
        listOperations.rightPop("mylist");//从右端删除元素
        Long size1 = listOperations.size("mylist");
        System.out.println(size1);

    }

在这里插入图片描述

在这里插入图片描述

测试Set类型

 	@Test
    public void testSet(){
        //sadd smembers scard sinter sunion srem
        SetOperations setOperations = redisTemplate.opsForSet();
        //向集合内插入成员
        setOperations.add("set1","王维","李白","白居易");
        setOperations.add("set2","王昌龄","李白","杜甫");
        //查看集合内的成员
        Set set1 = setOperations.members("set1");
        System.out.println(set1);
        //查看集合的大小
        Long size = setOperations.size("set1");
        System.out.println(size);
        //求两个集合的并集
        Set union = setOperations.union("set1", "set2");
        System.out.println(union);
        //求两个集合的交集
        Set intersect = setOperations.intersect("set1", "set2");
        System.out.println(intersect);
        //删除集合内的指定值
        Long remove = setOperations.remove("set1", "李白");
        System.out.println(remove);
    }

在这里插入图片描述

在这里插入图片描述

测试ZSet类型

 @Test
    public void testZSet(){
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        //zadd zrange zincrby zrem
        //添加成员
        zSetOperations.add("scores","三国演义",10);
        zSetOperations.add("scores","水浒传",9);
        zSetOperations.add("scores","红楼梦",10);
        zSetOperations.add("scores","西游记",8);
        //遍历成员
        Set score1 = zSetOperations.range("scores", 0, -1);
        System.out.println(score1);
        //加分
        zSetOperations.incrementScore("socres","三国演义",1);
        Set score2 = zSetOperations.range("scores", 0, -1);
        System.out.println(score2);
        //删除成员
        zSetOperations.remove("scores","三国演义","水浒传");
        Set score3 = zSetOperations.range("scores", 0, -1);
        System.out.println(score3);
    }

在这里插入图片描述

测试通用类型

	@Test
    public void testcommon(){
        //keys exists type del
        Set keys = redisTemplate.keys("*");
        System.out.println(keys);

        Boolean name = redisTemplate.hasKey("name");
        System.out.println(name);

        for(Object key:keys){
            DataType type = redisTemplate.type(key);
            System.out.println(type);
        }
        redisTemplate.delete("name");
    }

在这里插入图片描述

至此,完成了Redis各种数据类型的测试,注意,测试完成后,我们应该将SpringBootTest的注解注释掉,否则每次启动服务都会进行测试,影响速度。

应用场景

营业状态设置

营业状态只有两个值,没必要再设计一个数据表,因此可以使用Redis来存储。这个接口可以设置两个,分别是用户端与管理端

package com.sky.controller.admin;


import com.sky.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

@RestController("adminShopController")//注意这里要起个别名,因为User端有个名字一样的
@RequestMapping("/admin/shop")
@Api(tags = "店铺相关接口")
@Slf4j
public class ShopController {

    public static final String KEY = "SHOP_STATUS";

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 设置店铺的营业状态
     * @param status
     * @return
     */
    @PutMapping("/{status}")
    @ApiOperation("设置店铺的营业状态")
    public Result setStatus(@PathVariable Integer status) {
        log.info("设置店铺的营业状态为:{}",status == 1 ? "营业中" : "打烊中");
        redisTemplate.opsForValue().set(KEY, status);
        return Result.success();
    }

    /**
     * 获取店铺的营业状态
     * @return
     */
    @GetMapping("/status")
    @ApiOperation("获取店铺的营业状态")
    public Result<Integer> getStatus(){
        Integer status = (Integer) redisTemplate.opsForValue().get(KEY);
        log.info("获取到店铺的营业状态为:{}",status == 1 ? "营业中" : "打烊中");
        return Result.success(status);
    }

}

清除缓存

通过RedisTemplate对象操作Redis,这个功能多用在用户端。

其主要有清理缓存操作,由于我们的数据被修改了,那么原本的就要被清理掉

 private void clearCache(String pattern) {
        Set keys = redisTemplate.keys(pattern);
        redisTemplate.delete(keys);
    }

查询信息

查询菜品前,先查Redis,看是否有,没有则再查MySQL,并将查到的结果放入到Redis

	@GetMapping("/list")
    @ApiOperation("根据分类id查询菜品")
    public Result<List<DishVO>> list(Long categoryId) {
//        构造redis中的key,规则:dish_分类Id
        String key = "dish_" + categoryId;

//        查询redis中是否存在菜品数据
        List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
        if (list != null && list.size() > 0) {
//            如果存在,直接返回,无需查询数据库
            return Result.success(list);
        }


//        如果不存在,查询数据库,将查询到的数据放入redis中
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品

        list = dishService.listWithFlavor(dish);

//        放入redis
        redisTemplate.opsForValue().set(key, list);
        return Result.success(list);
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

单分支:if语句

示例&#xff1a; /*** brief how about if? show you here.* author wenxuanpei* email 15873152445163.com(query for any question here)*/ #define _CRT_SECURE_NO_WARNINGS//support c-library in Microsoft-Visual-Studio #include <stdio.h>#define if_state…

学习笔记------约束的管理

此篇记录FPGA的静态时序分析&#xff0c;在学习FPGA的过程中&#xff0c;越发觉得对于时序约束只是懂了个皮毛。现在记录一下自己的学习过程。 本文摘自《VIVADO从此开始》高亚军 为什么要进行约束&#xff1f;约束的目的是什么&#xff1f; 简单来说&#xff0c;就是需要在…

Unity(MVC思想)

MVC 一下演示使用MVC和不使用MVC的做法区别。 前两个没有使用MVC 主面板逻辑&#xff1a; mainPanel是该脚本名字 每个场景中不一定存在该面板&#xff0c;单纯的显隐需要去手动挂载过于麻烦。 所以自己读取创建面板出来(每个场景仅创建一次)&#xff0c;存下该面板&#xf…

OpenHarmony网络请求库-httpclient

简介 HTTP是现代应用程序通过网络交换数据和媒体的的主要方式。httpclient是OpenHarmony 里一个高效执行的HTTP客户端&#xff0c;使用它可使您的内容加载更快&#xff0c;并节省您的流量。httpclient以人们耳熟能详的OKHTTP为基础&#xff0c;整合android-async-http&#xf…

FPGA核心板在声呐系统中的应用

前言 声纳系统使用声脉冲来探测、识别和跟踪水下物体。一个完整的声纳系统是由一个控制和显示部件、一个发射器电路、一个接收器电路和同时能作为发射装置&#xff08;扬声器&#xff09;和探测装置&#xff08;高灵敏度麦克风&#xff09;的传感器组成。 声纳系统图 技术挑战…

list基础知识

list 1.list 的定义和结构 list 是双向链表&#xff0c;是C的容器模板&#xff0c;其接收两个参数&#xff0c;即 list(a,b) 其中 a 表示指定容器中存储的数据类型&#xff0c;b 表示用于分配器内存的分配器类型&#xff0c;默认为 list <int>; list 的特点&#xff1a;…

鸿蒙开发岗突增!它和前端开发到底有哪些区别和联系?

2024年1 月 18 日&#xff0c;鸿蒙 Next 预览版面向开发者正式开放申请。至此&#xff0c;鸿蒙原生应用版图已成型&#xff0c;这个中国自主研发的操作系统&#xff0c;正式走上了独立之路。 有许多的公司都陆续地加入了鸿蒙原生应用开发的队列&#xff0c;从年初宣布的200个应…

MySQL高负载排查方法最佳实践(15/16)

高负载排查方法 CPU占用率过高问题排查 使用mpstat查看cpu使用情况。 # mpstat 是一款 CPU 性能指标实时展示工具 # 能展示每个 CPU 核的资源视情况&#xff0c;同时还能将资源使用情况进行汇总展示 # 如果CPU0 的 %idle 已经为 0 &#xff0c;说明此核已经非常繁忙# 打印所…

京西商城——前端项目的创建以及前后端联调

创建VUE项目 在jingxi_shop_project文件夹中再创建一个 frontend 文件夹用来存放前端项目 /jingxi_shop_project/backend/jingxi_shop_project....../frontend/jingxi_shop_web......首先要安装 node.js 和 VUE cli&#xff0c;进入到项目目录内创建项目 vue create jingxi_…

【JavaEE多线程】Thread类及其常见方法(上)

系列文章目录 &#x1f308;座右铭&#x1f308;&#xff1a;人的一生这么长、你凭什么用短短的几年去衡量自己的一生&#xff01; &#x1f495;个人主页:清灵白羽 漾情天殇_计算机底层原理,深度解析C,自顶向下看Java-CSDN博客 ❤️相关文章❤️&#xff1a;清灵白羽 漾情天…

类和对象(中)(构造函数、析构函数和拷贝构造函数)

1.类的六个默认成员函数 任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 //空类 class Date{}; 默认成员函数&#xff1a;用户没有显示实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数 2.构造函数 构造函数 是一个 特殊的成员函数&a…

接口自动化入门: Http请求的域名与IP地址概念!

在进行接口自动化测试时&#xff0c;经常需要与服务器进行通信&#xff0c;这就涉及到了使用Http协议发送请求。在发送请求时&#xff0c;我们需要指定目标服务器的域名或者IP地址。下面将从0到1详细介绍域名与IP地址的概念及其在接口自动化测试中的应用。 本文从5个方面来书写…

3D可视化技术:研发基地的科技新篇章

在科技日新月异的今天&#xff0c;我们生活在一个充满无限可能性的时代。而在这个时代中&#xff0c;3D可视化技术正以其独特的魅力&#xff0c;引领着科技领域的新一轮变革。 3D可视化技术通过三维图像的方式&#xff0c;将现实世界或虚拟世界中的物体、场景等以立体、逼真的形…

改进下记录学习的小网站

Strong改进 结束&#xff1a;2024-4-14 打算投入&#xff1a;10h 实际消耗&#xff1a;12h 3m 学习总是不在状态。 我的时间花得很零散&#xff0c;也有点茫然。所以想尝试一下集中式地、一块一块地花&#xff0c;比如投入30个小时&#xff0c;去干一件事&#xff0c;这样就可…

npm怎么迁移到pnpm

下载的vue3模板用到了pnpm&#xff0c;就安装了一下 但是安装之后使用pnpm install 就发现包全被移动到ignored文件夹下面了,还报错 PS G:\Projects\gitProeject\TS_front> pnpm installWARN  Moving commitlint/config-conventional that was installed by a different …

继电器会不会被淘汰?

继电器作为一种电控制器件&#xff0c;其基本功能是在输入量达到一定条件时&#xff0c;使电气输出电路中的被控量发生预定的阶跃变化。 尽管现代电子技术发展迅速&#xff0c;新型产品不断涌现&#xff0c;但继电器因其独特的优势在许多应用领域仍然不可替代。 技术优势&#…

git 删除本地分支 删除远程仓库中的分支

语法&#xff1a; 删除本地分支 git branch -D <分支名>删除远程分支 git push <remote名称> <分支名> --delete 示例&#xff1a; 删除本地分支 git branch -D feature/test_listview删除远程分支 git push origin feature/test_listview --delete 两个…

FebHost:谁可以注册.CA加拿大域名?

在加拿大&#xff0c;互联网域名的注册管理遵循一套独特的规则。特别是对于代表加拿大身份的顶级域名“.ca”&#xff0c;其申请和注册过程涉及一些严格的条件。这些条件确保了只有符合特定标准的个人或实体才能获得这一具有国家象征意义的网络地址。 首先&#xff0c;想要注册…

实战1-批量爬取百度图片(上)

任务需求&#xff1a;输入关键字下载100个图片保存到本地&#xff0c;每个关键字单独存放一个文件夹&#xff08;GUI版&#xff09; 任务描述&#xff1a;当输入关键字时会爬取100个与关键词有关的图片到本地每个关键词单独保存到一个文件夹中&#xff0c;比如说我输入黑客下载…

Arduino源代码(ino)在Proteus中调试总结

一、前言 基于BluePill Plus开发板&#xff08;该板是毕设网红板&#xff09; BluePill Plus / WeAct Studio 微行工作室 出品 BluePill-Plus/README-zh.md at master WeActStudio/BluePill-Plus GitHub 首页-WeAct Studio-淘宝网 (taobao.com) 在Proteus中对应的例子是&…