当前位置: 首页>数据库>正文

Redis学习记录

Redis安装

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

Redis下载地址

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

Redis学习记录,Redis学习记录_redis,第1张

我们如何启动呢?

redis-server.exe redis.windows.conf

使用客户端连接redis:

redis-cli.exe

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

redis-cli.exe -h localhost -p 6379

Redis学习记录,Redis学习记录_redis_02,第2张

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

Redis学习记录,Redis学习记录_学习_03,第3张

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

Redis学习记录,Redis学习记录_Redis_04,第4张

随后在先前的命令后加上认证用户的密码即可。

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

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

Redis学习记录,Redis学习记录_Redis_05,第5张

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

Redis学习记录,Redis学习记录_System_06,第6张

随后我们就可以看到redis目前的使用情况了:

Redis学习记录,Redis学习记录_Redis_07,第7张

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学习记录,Redis学习记录_数据库_08,第8张

哈希操作常用命令

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学习记录,Redis学习记录_redis_09,第9张

Redis学习记录,Redis学习记录_数据库_10,第10张

列表操作命令

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

命令

含义

LPUSH key value1 [value2]

将一个或多个值插入到列表头部,这里的L不是List而是Left

LRANGE key start stop

获取列表指定范围内的元素

RPOP key

移除并获取列表最后一个元素

LLEN key

获取列表长度

Redis学习记录,Redis学习记录_学习_11,第11张

Redis学习记录,Redis学习记录_redis_12,第12张

集合操作命令

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

命令

含义

SADD key member1 [member2]

向集合添加一个或多个成员

SMEMBERS key

返回集合中的所有成员(members)

SCARD key

获取集合的成员数

SINTER key1 [key2]

返回给定所有集合的交集

SUNION key1 [key2]

返回所有给定集合的并集

SREM key member1 [member2]

删除集合中一个或多个成员

Redis学习记录,Redis学习记录_Redis_13,第13张

Redis学习记录,Redis学习记录_学习_14,第14张

Redis学习记录,Redis学习记录_System_15,第15张

有序集合操作命令

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学习记录,Redis学习记录_System_16,第16张

Redis学习记录,Redis学习记录_数据库_17,第17张

Redis学习记录,Redis学习记录_redis_18,第18张

通用命令操作

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

Redis学习记录,Redis学习记录_System_19,第19张

编写配置类,创建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());

Redis学习记录,Redis学习记录_redis_20,第20张

如果不对Key进行String序列化,则会调用默认的序列化器,结果便是下面这样:

Redis学习记录,Redis学习记录_redis_21,第21张

测试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");
    }

结果如下:

Redis学习记录,Redis学习记录_System_22,第22张

Redis学习记录,Redis学习记录_学习_23,第23张

测试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);

    }

Redis学习记录,Redis学习记录_学习_24,第24张

Redis学习记录,Redis学习记录_redis_25,第25张

测试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);
    }

Redis学习记录,Redis学习记录_数据库_26,第26张

Redis学习记录,Redis学习记录_redis_27,第27张

测试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);
    }

Redis学习记录,Redis学习记录_redis_28,第28张

测试通用类型

@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学习记录,Redis学习记录_学习_29,第29张

至此,完成了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);
    }



https://www.xamrdz.com/database/6ks1931086.html

相关文章: