Redis基于内存的key-value结构化NOSQL(非关系型)数据库

这篇具有很好参考价值的文章主要介绍了Redis基于内存的key-value结构化NOSQL(非关系型)数据库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Redis介绍

Redis基于内存的key-value结构的NOSQL(非关系型)数据库

非关系型数据库:表与表之间没有复杂的关系

Redis的优点

  • 基于内存存储,读写性能高 – Redis读的速度是110000次/S
  • 适合存储热点数据(商品、新闻资讯)
  • 它存储的value类型比较丰富,也称为结构化NoSQL数据库

Redis的缺点

Redis基于内存的key-value结构化NOSQL(非关系型)数据库,IDEA-Java各开发环境安装和常见问题解决,数据库,redis,nosql

Redis的安装

直接解压windows版压缩包就可以

启动:
①双击启动 无密码的形式

redis-server.exe

②cmd命令行启动

redis-server.exe  redis.windows.conf

前提是修改了配置文件

在配置文件中搜索 ctrl + f

foobared 

将注释 # 去掉 , 将 foobared 替换为 你的密码即可

Redis的连接

①双击启动 无密码的形式

redis-cli.exe

②cmd命令行启动

redis-cli.exe -a 你的密码

或远程连接

redis-cli.exe -h 192.168.166.60 -p 6379 -a 你的密码

验证登录

使用 ping 返回 pang 为成功

192.168.166.60:6379> ping
PONG

Redis的使用

更多命令可以参考Redis中文网:https://www.redis.net.cn

Redis中的数据类型

key 数据类型为 String
Value的数据类型有5种
① String *常用
② Hash *常用
③ List 有序
④ Set 无序
⑤ ZSet 有序

String的使用

get set
192.168.166.60:6379> set name zs
OK
192.168.166.60:6379> get name
"zs"
192.168.166.60:6379>

重复set会覆盖

setex(expire)ttl
192.168.166.60:6379> setex age 10 18
OK
192.168.166.60:6379> get age
"18"
192.168.166.60:6379> ttl age
(integer) -2
192.168.166.60:6379> setex age 10 18   //10 秒过期
OK
192.168.166.60:6379> ttl age
(integer) 8
192.168.166.60:6379> ttl age
(integer) 6
192.168.166.60:6379> get age
"18"
192.168.166.60:6379> ttl age
(integer) -2
192.168.166.60:6379> get age
(nil)
192.168.166.60:6379>

过期是-2
永久是-1
正数是倒计时过期时间

setnx(not exit)

分布式锁(应用场景)

不能覆盖value

192.168.166.60:6379> setnx sex female
(integer) 1
192.168.166.60:6379> setnx sex male
(integer) 0
192.168.166.60:6379> get sex
"female"
192.168.166.60:6379>

Hash

Hash类型极其类似于java中的Map,值里面可以存放一组组的键值对

该类型非常适合于存储java中对象的信息

192.168.166.60:6379> hset user1 name zs
(integer) 1
192.168.166.60:6379> hset user1 age 18
(integer) 1
192.168.166.60:6379> hgetall user1
1) "name"
2) "zs"
3) "age"
4) "18"
192.168.166.60:6379> hkeys user1
1) "name"
2) "age"
192.168.166.60:6379> hvals user1
1) "zs"
2) "18"
192.168.166.60:6379> hdel user1 name [可以删除多个字段 空格 隔开]
(integer) 1
192.168.166.60:6379> hkeys user1
1) "age"
192.168.166.60:6379> hvals user1
1) "18"

List列表(队列)

List类型底层是一个双向字符串链表。里面的元素是有序的,可重复的

我们可以从链表的任何一端进行元素的增删

* 新增
	左压入
		lpush key value1 value2 ...
	右压入
		rpush key value1 value2 ...
		
* 查询元素(闭合区间)
		lrange key  开始索引  结束索引
		
* 列表长度
		llen key
* 删除元素
	左弹出
		lpop key
	右弹出
		rpop key

Set集合

Set类型底层是一张hash表。里面的元素是无序的,不可重复的

* 新增
		sadd key value1 value2 ...
		
* 查询元素
		smembers key
		
* 查询集合数量
		scard key
		
* 删除元素	
		srem key value1 value2 ...
* 求集合的交集:
	sinter key1 key2
		
* 求集合的并集:
		sunion key1 key2	

* 求集合的差集:
		sdiff key1 key2

ZSet集合

Zset,也称sortedSet, 在Set的基础上,加入了有序功能,在添加元素的时候,允许指定一个分数,它会按照这个分数排序

* 新增
		zadd key score1 value1 score2 value2 ...
		
* 查询
	升序
		zrange key start end [withscores] 
	降序	
		zrevrange key start end [withscores] 
		
* 加分
		zincrby key increment member 

* 删除
		zrem key value

Redis 通用命令

192.168.166.60:6379> exists sex
(integer) 1
192.168.166.60:6379> get sex
"female"
192.168.166.60:6379> keys *
1) "sex"
2) "name"
3) "user1"
192.168.166.60:6379> type sex
string
192.168.166.60:6379> type name
string
192.168.166.60:6379> type user1
hash
192.168.166.60:6379> select 1
OK
192.168.166.60:6379[1]> select 0
OK
192.168.166.60:6379> select 1
OK
192.168.166.60:6379[1]> type name
none
192.168.166.60:6379[1]> keys *
(empty list or set)
192.168.166.60:6379[1]> select 0
OK
192.168.166.60:6379> keys *
1) "sex"
2) "name"
3) "user1"
192.168.166.60:6379>

Redis图形客户端

在我的资源中有Redis-DeskTop软件,解压安装即可使用

Redis在Java中的使用

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

RedisTemplate

  • ValueOperations:简单的键值对数据操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作
  • HashOperations:hash类型的数据操作
  • ListOperations:list类型的数据操作

导入坐标

在sky-server模块导入spring data redis依赖

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

添加redis配置

application-dev.yml

sky:
  redis:
    host: localhost
    port: 6379
    password: itheima

application.yml

spring:
  redis:
    host: ${sky.redis.host}
    port: ${sky.redis.port}
    password: ${sky.redis.password}

RedisTemplate测试类


@SpringBootTest 
public class RedisTest {

    @Autowired
    private RedisTemplate redisTemplate;



    // 获取五种操作类型的对象
    @Test
    public void test()throws Exception{
        // 1.字符串类型
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 2.哈希类型
        HashOperations hashOperations = redisTemplate.opsForHash();
        // 3.列表类型
        ListOperations listOperations = redisTemplate.opsForList();
        // 4.集合类型
        SetOperations setOperations = redisTemplate.opsForSet();
        // 5.有序集合类型
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
    }
}

API

操作字符串类型数据

// 字符串类型
@Test
public void test02()throws Exception{
    // 1.字符串操作对象
    ValueOperations valueOperations = redisTemplate.opsForValue();

    // 存
    // valueOperations.set("mystr","i am a string");
    // 取
    // System.out.println(valueOperations.get("mystr"));

    // 存短信验证码,5分钟有效时间
    // valueOperations.set("sms:13500135001","223355", Duration.ofSeconds(300));


    //存一个java对象(要求实现序列化接口)
    Category category = Category.builder()
        .name("烤鱼套餐")
        .status(1)
        .createTime(LocalDateTime.now())
        .build();


    // valueOperations.set("category",category);

    // 查询java对象
    System.out.println(valueOperations.get("category"));
}

操作哈希类型数据

// 哈希类型
@Test
public void test03()throws Exception{
    // 2.哈希操作对象
    HashOperations hashOperations = redisTemplate.opsForHash();

    // 存
    hashOperations.put("user:1","name","饭岛爱");
    hashOperations.put("user:1","age",18);

    // 取一个
    System.out.println(hashOperations.get("user:1", "age"));

    System.out.println("--------------------------");
    // 取出所有元素
    Set hkeys = hashOperations.keys("user:1");
    hkeys.forEach(hkey->{
        System.out.println(hashOperations.get("user:1", hkey));
    });

    // 删除
    hashOperations.delete("user:1","age");
}

操作列表类型数据

// 列表类型
@Test
public void test04()throws Exception{
    // 3.列表操作对象
    ListOperations listOperations = redisTemplate.opsForList();
    // 左压入
    listOperations.leftPushAll("mylist","a","b","c");

    // 查询    c b a
    List mylist = listOperations.range("mylist", 0, -1);
    System.out.println(mylist);

    // 右弹出
    System.out.println(listOperations.rightPop("mylist"));


    // 查询  c b
    List mylist1 = listOperations.range("mylist", 0, -1);
    System.out.println(mylist1);
}

操作集合类型数据

// 集合类型
@Test
public void test05()throws Exception{
    // 4.集合操作对象
    SetOperations setOperations = redisTemplate.opsForSet();

    // 存 
    // setOperations.add("tom","唱","跳","rap","打篮球");
    // 存 
    // setOperations.add("jack","爱坤","唱","rap");


    // 查询
    Set set = setOperations.members("jack");
    System.out.println(set);


    // 交集
    System.out.println(setOperations.intersect("tom", "jack"));

    // 并集
    System.out.println(setOperations.union("tom", "jack"));

    // 删除
    setOperations.remove("tom","rap");
}

操作有序集合类型数据

// 有序集合类型
@Test
public void test06()throws Exception{
    // 5.有序集合操作对象
    ZSetOperations zSetOperations = redisTemplate.opsForZSet();

    // 存
    // zSetOperations.add("java","tom",66.4);
    // zSetOperations.add("java","jack",45.2);
    // zSetOperations.add("java","飞机",23.2);


    // 苦练安其拉
    zSetOperations.incrementScore("java","tom",30);

    // 查询 降序
    System.out.println(zSetOperations.reverseRange("java", 0, -1));

}

通用操作

// 通用操作
@Test
public void test07()throws Exception{
    // 查询  keys c*
    Set keys = redisTemplate.keys("c*");
    System.out.println(keys);

    // 批量删除
    redisTemplate.delete(keys);

    // 判断key是否存在
    System.out.println(redisTemplate.hasKey("tom"));
}

统一处理时间格式配置类

主要是为了方便使用图像化客户端进行对redis中存储数据的查看和对日期格式的处理(不是必须的)

package com.sky.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.cache.annotation.CachingConfigurerSupport;
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.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

// Redis配置类
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        //原生RedisTemplate
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);

        //json序列化
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = getJackson2JsonRedisSerializer();

        // -------- 设置key value 序列化方式 --------
        // key采用String的序列化方式
        template.setKeySerializer(RedisSerializer.string());
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(RedisSerializer.string());
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    private Jackson2JsonRedisSerializer getJackson2JsonRedisSerializer() {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        //设置ObjectMapper访问权限
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //记录序列化之后的数据类型,方便反序列化
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL);

        //LocalDatetime序列化,默认不兼容jdk8日期序列化
        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addDeserializer(LocalDate.class,
                new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        timeModule.addDeserializer(LocalDateTime.class,
                new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        timeModule.addSerializer(LocalDate.class,
                new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        timeModule.addSerializer(LocalDateTime.class,
                new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        //关闭默认的日期格式化方式,默认UTC日期格式 yyyy-MM-dd’T’HH:mm:ss.SSS
        om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        om.registerModule(timeModule);

        jackson2JsonRedisSerializer.setObjectMapper(om);
        return jackson2JsonRedisSerializer;
    }
}

在项目中的应用

ShopController设置状态

@RestController
@RequestMapping("/admin/shop")
public class ShopController {

    @Autowired
    private RedisTemplate redisTemplate;

    // 设置店铺状态
    @PutMapping("/{status}")
    public Result setStatus(@PathVariable("status") Integer status) {
        // 调用redis设置
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("SHOP_STATUS", status);
        return Result.success();
    }
}

用户端查询营业状态

// 店铺管理
@RestController
@RequestMapping("/user/shop")
public class AppShopController {

    @Autowired
    private RedisTemplate redisTemplate;


    // 查询店铺状态
    @GetMapping("/status")
    public Result getShopStatus(){
        Integer status = (Integer) redisTemplate.opsForValue().get("SHOP_STATUS");
        return Result.success(status);
    }
}

管理端查询营业状态

// 获取店铺的营业状态
@GetMapping("/status")
public Result getStatus(){
    Integer status = (Integer) redisTemplate.opsForValue().get("SHOP_STATUS");
    return Result.success(status);
}

菜品缓存

Redis基于内存的key-value结构化NOSQL(非关系型)数据库,IDEA-Java各开发环境安装和常见问题解决,数据库,redis,nosql
读取数据的时候:

  • 先判断缓存中有无数据,
    • 若有直接返回
    • 若无,再查询mysql,将数据放入redis中一份,最后返回

写数据的时候:

  • 保证redis和mysql中数据一致.一旦有写操作的时候,删除缓存中数据

redis数据存储设计

首先明确在redis中存储的数据格式,必须确定的是key部分要包含查询条件文章来源地址https://www.toymoban.com/news/detail-671695.html

redis缓存的key(DISH:分类的id) redis缓存的value
DISH:1 List<DishVo>的json

缓存菜品数据

@RestController
@RequestMapping("/user/dish")
@Slf4j
public class AppDishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private RedisTemplate redisTemplate;

    // 根据分类id查询菜品列表(小程序段)
    @GetMapping("/list")
    public Result getList(@RequestParam Long categoryId) {
        List<DishVO> voList = null;
        // ---------------------start
        // 先查询redis中是否有该分类的菜品缓存
        String dishKey = "DISH:" + categoryId;
        if (redisTemplate.hasKey(dishKey)) {
            log.info("查询缓存...");
            voList = (List<DishVO>) redisTemplate.opsForValue().get(dishKey);
            return Result.success(voList);
        }
        // ---------------------end
        // 封装dto条件
        DishPageDTO dishPageDTO = DishPageDTO.builder()
                .categoryId(categoryId)
                .status(1)
                .build();

        // 调用service查询,返回结果
        log.info("查询数据库...");
        voList = dishService.getParamList(dishPageDTO);
        // --------------------------  start
        // 将数据库数据同步到缓存
        redisTemplate.opsForValue().set(dishKey, voList);
        // --------------------------  end

        return Result.success(voList);
    }
}

缓存一致性(了解什么是延迟双删)

@Autowired
private RedisTemplate redisTemplate;

// 菜品新增
@PostMapping
public Result saveDishWithFlavor(@RequestBody DishDTO dishDTO) {
    dishService.saveDishWithFlavor(dishDTO);

    // 清理缓存
    redisTemplate.delete("DISH:"+dishDTO.getCategoryId());


    return Result.success();
}


// 修改菜品
@PutMapping
public Result updateById(@RequestBody DishDTO dishDTO) {
    dishService.updateById(dishDTO);

    // 清理缓存
    Set dishKey = redisTemplate.keys("DISH*");
    redisTemplate.delete(dishKey);

    return Result.success();
}


// 删除菜品
@DeleteMapping
public Result deleteBatch(@RequestParam List<Long> ids) {
    dishService.deleteBatch(ids);

    // 清理缓存
    Set dishKey = redisTemplate.keys("DISH*");
    redisTemplate.delete(dishKey);


    return Result.success();
}


// 启用禁用
@PostMapping("/status/{status}")
public Result startOrStop(
    @PathVariable("status") Integer status,
    @RequestParam Long id) {
    dishService.startOrStop(status, id);

    // 清理缓存
    Set dishKey = redisTemplate.keys("DISH*");
    redisTemplate.delete(dishKey);

    return Result.success();
}

到了这里,关于Redis基于内存的key-value结构化NOSQL(非关系型)数据库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 结构化数据、非结构化数据、半结构化数据

    结构化的数据一般是指可以使用关系型数据库表示和存储,可以用二维表来逻辑表达实现的数据。例如:需要多少个属性,每个属性什么类型,每个属性的取值范围等等,类似下图所示, 提前定义好了一个二维矩阵的元数据 ,包含有列名称、列的类型、列的约束等:   可见

    2024年02月09日
    浏览(67)
  • 基于Python的语义视频搜索:使用结构化相似度测量指数(SSMI)和图像字幕网络实现的分步解析与实战示例

    在如今这个视频信息愈加丰富的时代,如何有效地搜索、分析和管理大量的视频数据变得越来越重要。本文旨在解释我们如何使用Python和一些先进的计算机视觉技术来实现对视频库的语义搜索,即,我们可以通过自动生成的摘要来搜索视频数据库。 在这个过程中,我们首先将

    2024年02月16日
    浏览(49)
  • 第五章 结构化设计

    一种软件开发活动,定义实现需求规约所需的软件结构。 结构化设计分为: (1)总体设计:确定系统的整体模块结构,即系统实现所需要的软件模块以及这些模块之间的调用关系。 (2)详细设计:详细描述模块。 体系结构设计(MSD) 接口设计 数据设计 实现软件设计的目标对结

    2024年02月08日
    浏览(59)
  • 【numpy基础】--结构化

    目前为止,介绍的 numpy 数组基本都是关于数值的,其实, numpy 本身就是一个用于数值计算的基础库。 不过,除了数值计算之外, numpy 也能够支持 结构化数组 。 numpy 的数组为了提高计算性能,要求数组的数据类型要一致。 但是现实情况下,我们经常遇到不是纯数值的数组

    2024年02月12日
    浏览(45)
  • elasticsearch结构化查询

    在上一篇中我们介绍了DSL相关的知识,接下来我们将会学习elasticsearch的结构化查询,同时也实践一下上一篇的DSL的查询用法 从《Elasticsearch权威指南》上摘取部分解释如下: 从上面的定义我们可以看出来结构化查询最重要的就是是否匹配么人并不是很关心相关性和分值计算。

    2024年02月01日
    浏览(48)
  • SQL:结构化查询语言

    创建一张表并插入数据: 以下常用函数以MySQL为例,其它数据库类似

    2024年02月06日
    浏览(49)
  • elasticsearch结构化查询(一)

    在上一篇中我们介绍了DSL相关的知识,接下来我们将会学习elasticsearch的结构化查询,同时也实践一下上一篇的DSL的查询用法 从《Elasticsearch权威指南》上摘取部分解释如下: 从上面的定义我们可以看出来结构化查询最重要的就是是否匹配么人并不是很关心相关性和分值计算。

    2024年02月05日
    浏览(63)
  • WPF 界面结构化处理

    WPF 框架是开源的,但是不能跨平台,可以使用MAUI,这个框架可以跨平台,WPF源码可以在github上下载,下载地址:https://gitbub.com/dotnet/wpf。 框架结构 如图 XAML:eXtensible Application Markup Language的英文缩写,相应的中文名称为:可扩展应用程序标记语言。 命名空间 默认 映射:x/

    2024年02月13日
    浏览(61)
  • 结构化流的介绍

    目录 有界数据和无界数据 有界数据  无界数据  结构化流 基本介绍 入门案例 结构化流的编程模型 数据结构 数据源(Source) File Source Kafka Source(Spark 和 Kafka 整合) 整合Kafka准备工作 从kafka中读取数据 流式处理 批处理  数据写入Kafka中 流式处理 批处理 有界数据 数据有固定的开

    2024年01月15日
    浏览(63)
  • Structured Concurrency:结构化并发

    https://ericniebler.com/2020/11/08/structured-concurrency/ 是什么:一种确保子操作在父操作之前完成的方式,类似函数在调用函数之前完成。 最典型的结构化并发:C++20的协程 意义:它通过使异步生存期与普通C++词法作用域相对应,为异步程序带来了现代C++风格,并且不需要引用计数(

    2024年02月05日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包