Redis 概述与应用


Redis

1. Redis 介绍

  • Redis(Remote Dictionary Server)是用C语言开发的一个开源的高性能键值对数据库。它的所有数据都是保存在 内存 中,这也就决定了其读写速度之快,是其它硬盘保存数据的系统所无法匹敌的。
  • 官方曾经给出过一组测试数据,50个并发执行 100000个请求:读的速度是 110000次/s,写的速度是 81000次/s
    在这里插入图片描述

2. Redis 安装和使用

a. 下载

b. Windows 版安装

c. 目录

在这里插入图片描述

  • redis.windows.conf:配置文件
  • redis-cli.exe:Redis 的客户端
  • redis-server.exe:Redis 服务器端

d. 启动

  • 推荐使用命令行的方式
  • 在当前解压后的目录下 cmd 进入 dos 窗口
  • 先启动 redis-server.exe redis.windows.conf
    在这里插入图片描述
  • 新建窗口,再启动 redis-cli.exe
    在这里插入图片描述

3. Redis 客户端图形化工具

4. Redis 数据结构(重点)

  • Redis 采用的键值对存储数据,键(key)的类型只能为 字符串,值(value)支持五种数据类型:
    1. 字符串:String
    2. 哈希:HashMap
    3. 双向链表:LinkedList,有序且能重复,可以左压栈也可以右压栈
    4. 无序集合:HashSet,无序且不能重复
    5. 有序集合:LinkedHashSet,有序且不能重复

5. Redis 命令操作(重点)

  • Redis 命令是用来操作 Redis 数据库的,类似于操作 MySql 数据库时的 SQL 语句。
  • 只需要学习 SQL 基本就可以操作关系型数据库(1972 年诞生);但是 Redis 命令,在非关系型数据库中,只能在 Redis 中使用(只有十几年的发展经历,所以没有一定的开发规范)
  • Redis 的命令根据要操作的值(value)的数据结构的不同而不同,每种数据类型都有自己的操作命令。

a. String 字符串

  • 字符串类型是 Redis 中最为基础的数据存储类型。
  • 在 Redis 中字符串类型的 Value 最多可以容纳的数据长度是 512 MB(超过这个上限,可以改用 HBase)。
* 新增
		set key 'value'
		value 的值有空格需要加引号,没有空格不需要加引号
* 查询
		get key
* 删除	
		del key
		成功则返回 1
* 新增并指定存活时间
		setex key 存活时间 'value'
		单位秒
* 查看存活时间
		ttl key  
* 主键自增器 
		incr key
		value 的值默认加 1
		需要 value 是整型

b. Hash 哈希

  • Hash 类型极其类似于 Java 中的 Map,值里面可以存放一组组的键值对,该类型非常适合于存储 Java 中对象的信息。
* 新增
		hset key hkey hvalue
* 查询
		hget key hkey
		hgetall key
* 删除
		hdel key hkey
		del key

在这里插入图片描述

c. List 链表

  • List 类型底层是一个双向字符串链表。里面的元素是有序的,可重复的,可以从链表的任何一端进行元素的增删。
* 新增
		lpush key value 将元素压入左侧顶端
		rpush key value 将元素压入右侧顶端
		建议只用其中一种
* 查询
		lrange key start end 从左向右查询
		start 为 0,end 为 -1 是查询所有
* 删除
		lpop key 将左侧顶端元素弹出
		rpop key 将右侧顶端元素弹出

在这里插入图片描述

d. Set 集合(无序)

  • Set 类型底层是一张 hash 表。里面的元素是无序的,不可重复的。
* 新增
		sadd key value
* 查询
		smembers key
* 删除
		srem key value 删除指定元素
		del key 删除整个 set 集合

e. ZSet 集合(有序)

  • Zset,也称 sortedSet,在 Set 的基础上,加入了有序功能,在添加元素的时候,允许指定一个分数,它会按照这个分数排序。
* 新增
		zadd key score value
* 查询
		zrange key start end [withscores] 升序
		zrevrange key start end [withscores] 降序
		加上 withscores 会显示分数,不加 withscores 只显示元素
* 删除
		zrem key value 删除指定元素
		del key 删除 zset 集合

f. 通用命令

* 模糊查询键
		keys *
		* 是通配符,表示所有
* 删除多个键
		del key [key] [key]
		返回的数就是被影响的 key 的数量
* 根据键判断记录是否存在
		exists key
		返回的值 0 是 false,1 是 true
* 根据键判断值类型 
		type key
		很重要,时间久了可以用它来判断并进行相应操作
* 选择数据库
		select 0~15
		默认是 0 库,一般也使用 0 库
* 清空当前数据库
		flushdb
		慎重使用,开发中不允许使用
* 清空所有数据库
		flushall
		慎重使用,开发中不允许使用

6. Redis 持久化(面试题)

  • Redis 的数据都是存在在内存之中的,那么这样一旦出现宕机,势必会导致数据的丢失,这就需要持久化操作,也就是要将 Redis 在内存中的数据写到硬盘上保存。
  • 注意,Redis 虽然有持久化操作,但是其全部数据依旧都在内存中存在,也就是说硬盘上的只是为了安全和备份。
  • Redis 提供了两种数据持久化的方式,分别是 RDB 和 AOF。

a. RDB(默认开启)

  • 在 Redis 运行期间,根据指定时间节点对内存的数据进行快照拍摄,持久化到磁盘文件(默认文件 dump.rdb,乱码)
  • 指定时间规则拍摄快照:在 redis.windows.conf 中指定
    save 900 1
    save 300 10
    save 60 10000
    在这里插入图片描述

b. AOF(默认关闭,需要手动开启)

  • 在 Redis 运行期间,以日志记录的方式监听 set 操作,持久化到磁盘文件(默认文件 appendonly.aof,每步操作可查看,Redis 重启后逐步加载)
  • 开启 AOF:修改 redis.windows.conf 中的 appendonly no 为 appendonly yes
  • 日志持久化机制
    • appendfsync always 每次执行 set 操作时都会持久化一次;
    • appendfsync everysec 每秒钟持久化一次(默认,因为 Redis 每秒读写速度很快,所以这种折中方案比第一种更合适);
    • appendfsync no 根据服务器环境,CPU 不忙的情况,持久化一次。

c. 小结

  • RDB:把 Redis 作为缓存来用。
    • 优点:性能高
    • 缺点:可能会丢失部分数据
  • AOF:把 Redis 作为独立数据库。
    • 优点:几乎不会丢失数据
    • 确定:性能较差
  • 这二种持久化机制可以共存。

7. 应用场景

a. 缓存

在这里插入图片描述

b. 秒杀

在这里插入图片描述

c. 微博热搜

在这里插入图片描述

d. 分布式 Session

在这里插入图片描述

e. 验证码存储

  • 通过将验证码放到 Redis 中,可以实现对其存货时间的精准控制。
    在这里插入图片描述

Jedis

  • Redis 作为一款优秀的缓存服务器存在,大多数语言都提供了连接 Redis 的驱动包,在 Java 中,比较出名的是 Jedis 和 Redisson,我们今天以 Jedis 为例学习,看看如何是用程序操作 Redis。

1. Jedis 快速入门

  • 常用 API:
方法 解释
new Jedis(host, port) 创建 Jedis 对象,参数 host 是 Redis 服务器地址,参数 port 是 Redis 服务端口
set(key,value) 设置字符串类型的数据
get(key) 获得字符串类型的数据
hset(key,field,value) 设置哈希类型的数据
hget(key,field) 获得哈希类型的数据
lpush(key,values) 设置列表类型的数据
lpop(key) 列表左面弹栈
rpop(key) 列表右面弹栈
del(key) 删除指定的 key
  • 在测试 Jedis 代码之前,一定要保证 Redis 环境正常运行。Windows 有时需要重启 Server。

a. 导入相关座标

在这里插入图片描述

b. 编写代码

package com.regino.test;

import org.junit.Test;
import redis.clients.jedis.Jedis;

public class JedisTest {

    // 向Redis设置String类型的数据
    @Test
    public void test01() throws Exception {
        // 1.创建连接对象
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        // 2.调用set方法设置数据,cmd会将中文转为Unicode
        jedis.set("Regino", "你好");
        // 3.释放资源,底层是Socket
        jedis.close();
    }

    // 查询String类型数据
    @Test
    public void test02() throws Exception {
        // 1.创建连接对象
        Jedis jedis = new Jedis(); // 默认连接 127.0.0.1 主机 和 6379 端口
        // 2.调用get方法获取
        String java = jedis.get("Regino");
        System.out.println(java);
        // 3.释放资源
        jedis.close();
    }
}

在这里插入图片描述

2. Jedis 连接池

  • Jedis 连接资源的创建与销毁是非常消耗性能的,所以我们不希望频繁的创建和销毁它。基于这样的需求,就有了 jedisPool 技术。

a. 快速入门

package com.regino.test;

import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolTest {

    // 测试Jedis内置的连接池
    @Test
    public void test01() throws Exception {

        // 连接池配置对象
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(100); // 最大连接数
        jedisPoolConfig.setMaxWaitMillis(3000);// 最大等待时间,单位是毫秒,超过会自动抛出异常
        jedisPoolConfig.setMaxIdle(10); // 最大空闲连接数,释放没用的资源

        // 创建连接池对象
        JedisPool jedisPool = new JedisPool("localhost", 6379); // 建议使用IP,用localhost只能连接本地

        // 从池中获取连接
        Jedis jedis = jedisPool.getResource();

        // 操作API
        jedis.hset("myhash", "id", "1");

        // 归还到连接池
        jedis.close();
    }
}

在这里插入图片描述

b. 抽取为连接池工具类

在这里插入图片描述

package com.regino.travel.util;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.ResourceBundle;

/*
 *   Jedis工具类
 * */
public class JedisUtils {

    private static JedisPool jedisPool;

    private static String host;
    private static Integer port;
    private static Integer maxTotal;
    private static Integer maxIdle;

    // 初始化连接池
    static {
        try {
            ResourceBundle jedis = ResourceBundle.getBundle("jedis");

            // 读取配置文件给变量赋值
            // 获取类加载读取jedis.properties,获取io流
            InputStream is = JedisUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
            // 创建properties对象 加载io流
            Properties properties = new Properties();
            properties.load(is);
            // 给变量赋值
            host = properties.getProperty("jedis.host");
            port = Integer.parseInt(properties.getProperty("jedis.port"));
            maxTotal = Integer.parseInt(properties.getProperty("jedis.maxTotal"));
            maxIdle = Integer.parseInt(properties.getProperty("jedis.maxIdle"));

            // 创建连接池配置对象
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxTotal(maxTotal);
            jedisPoolConfig.setMaxIdle(maxIdle);
            // 创建连接池对象
            jedisPool = new JedisPool(jedisPoolConfig, host, port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 提供获取Jedis连接的方法
    public static Jedis getJedis() {
        return jedisPool.getResource();
    }
}

原文链接:https://qwert.blog.csdn.net/article/details/106290370

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章