第19周JavaWeb编程实战-MyBatis实现OA系统 3.Redis入门

Redis 学习笔记

1. Redis 简介

什么是 Redis?

  • Redis 是一个基于内存的 NoSQL 数据库,专门用于处理高并发和分布式项目中常见的性能瓶颈问题。
  • NoSQL:全称为 “Not Only SQL”。与传统关系型数据库不同,NoSQL 数据库通常无需表结构、外键关系等复杂设计,数据以键值对形式存储,适合大规模、高性能的分布式环境。

Redis 的由来

  • Redis 的开发者是意大利人 Salvatore Sanfilippo。他在创建网站过程中,发现传统数据库(如 MySQL 和 Oracle)的硬盘存储带来性能瓶颈,决定开发基于内存的数据库来解决这个问题,进而诞生了 Redis。
  • Redis Labs:Salvatore 在开发 Redis 后成立了 Redis Labs,目前为全球超过 8000 家公司提供 Redis 解决方案。

Redis 的核心特性

  • 基于内存:Redis 将数据存储在内存中,极大提升了读取速度和性能,特别适用于高并发场景。
  • 高性能:相比传统的关系型数据库,Redis 的数据检索速度可以提升 10 倍甚至更多。
  • 持久化:虽然 Redis 是基于内存存储,但它也支持将数据持久化到磁盘,确保在重启或当机后数据不丢失。

什么是 NoSQL?

  • Not Only SQL:NoSQL 数据库不局限于 SQL 的关系型数据结构,通常采用键值对(Key-Value)形式存储数据。
  • 与关系型数据库的区别
    • 关系型数据库的典型特征是表结构、主键、外键以及复杂的表关系(如一对一、一对多、多对多)。
    • 关系型数据库在处理大规模数据或分布式数据扩展时效率较低,而 NoSQL 数据库可以有效应对这些挑战。
    • NoSQL 数据库适合处理非结构化数据,具有高可扩展性和灵活性。

Redis 的数据存储方式

  • Redis 的数据是以 键值对(Key-Value) 形式存储的,这类似于编程语言中的 MapHashMap,每个键(Key)对应一个值(Value)。
  • 键值对的存储方式使得 Redis 在查询时具有极高的效率,特别是在需要快速数据读取和写入的场景。

内存数据库的优势

  • 速度快:由于数据存储在内存中,Redis 的数据处理速度比传统的硬盘存储数据库快得多。适用于处理大量并发请求的场景,如电商网站、社交媒体等。
  • 高并发处理:在电商场景中,通过将商品数据从传统数据库如 MySQL 中提取并缓存在 Redis 中,可以大大提升数据的检索速度,避免传统硬盘存储的瓶颈。

Redis 的持久化功能

  • 尽管 Redis 是基于内存的数据库,但它支持将内存数据定期或实时持久化到磁盘中,防止数据丢失。
  • RDB(快照)和 AOF(追加日志)是 Redis 的两种持久化机制,分别用于定期存储和记录每个操作。

Redis 在现代互联网中的作用

  • 随着硬件价格的下降,内存的普及,Redis 等基于内存的数据库开始被广泛应用。特别是近年来,互联网行业对高并发处理的需求越来越大,Redis 作为缓存解决方案备受青睐。

2.Redis 核心特性

2. 1. 速度快

  • Redis 最显著的特点是极高的速度。在峰值情况下,Redis 每秒可以处理 十万次操作。即使在常规场景下,Redis 每秒处理 两三万次操作 也是可以保证的。这种速度远远超过传统的关系型数据库(如 MySQL、Oracle),因为 Redis 是基于内存操作,读写速度非常快。

2. 2. 多语言支持

  • Redis 拥有广泛的开发语言支持。无论是常见的 JavaC#Python 等开发语言,还是其他主流开发工具,Redis 都有良好的兼容性和交互工具。同时,由于 Redis 是开源的,开发者甚至可以为特定需求自定义 Redis 交互工具。

2. 3. 持久化机制

  • Redis 提供了两种持久化机制,确保数据在 Redis 失去服务后不丢失:
    • RDB (Redis DataBase):基于全量备份的持久化方案。
    • AOF (Append Only File):基于日志更新的持久化方案,通过记录每次操作来持久化数据。

2. 4. 多种数据结构支持

  • Redis 支持丰富的数据类型和结构,如:

    • 字符串 (String):最基本的数据类型。
    • 列表 (List):类似于数组的数据结构。
    • 哈希 (Hash):键值对的映射集合。
    • 集合 (Set):无序且唯一的集合。
    • 有序集合 (Sorted Set):带有排序的集合结构。

    这些数据结构帮助开发者灵活地处理各种类型的数据需求。

2. 5. 主从复制

  • 主从复制是指多个 Redis 服务器之间保持数据同步的机制。通过主从复制,数据可以在多台 Redis 实例之间保持一致,这样即使某台 Redis 出现问题,其他服务器也能继续提供服务。

2. 6. 分布式与高可用

  • 分布式:Redis 支持将数据分布到多台服务器上,这些服务器可以位于不同地域。例如,一台服务器位于广州,另一台服务器位于北京,程序可以根据地理位置就近访问 Redis,减少网络延迟。
  • 高可用性:Redis 提供了 Sentinel 哨兵机制,用于监控集群中的 Redis 实例,自动发现出现故障的节点并进行切换,确保 Redis 服务的持续可用性,避免单点故障。

2. 7. 哨兵机制 (Sentinel)

  • Redis 的哨兵机制 (Sentinel) 提供了一种自动化的高可用解决方案,可以监控 Redis 实例并在出现问题时自动完成故障转移。哨兵可以监测主从关系中的主节点状态,如果主节点出现故障,它会自动将从节点提升为主节点,从而确保系统的稳定运行。

3.Redis Linux安装

参考官网

sudo apt-get install lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis

连接到 Redis
一旦 Redis 运行,您可以通过运行以下命令对其进行测试redis-cli:

redis-cli

使用以下命令测试连接ping:

127.0.0.1:6379> ping
PONG
sudo vim /etc/redis/redis.conf #找到6379更改默认端口
#找到databases可以更改数据库个数
#找到requirepass可以修改密码
#找到dir可以指定数据保存路径
redis-cli -p 6380 #找到更改的端口号

4. Redis 通用命令课程笔记

课程简介

本节课介绍了 Redis 中一些最常用的通用命令,这些命令涵盖了 Redis 数据库的选择、数据的设置和获取、数据库中的键管理、过期时间设置等方面。这些命令将在后续学习中反复用到。

Redis 通用命令

  1. select

    • 用于选择不同编号的数据库。
    • Redis 默认有 16 个数据库(0-15)。
    • 使用 select 命令选择指定编号的数据库:
      select 0  # 选择0号数据库
      select 1  # 选择1号数据库
      
  2. set

    • 设置键值对数据,格式为 set key value
    • 例如:
      set name lily  # 设置 key=name, value=lily
      
  3. get

    • 获取指定键的值,格式为 get key
    • 例如:
      get name  # 获取 key=name 对应的值
      
  4. keys

    • 列举当前数据库中所有匹配的键,使用通配符查询:
      keys *     # 列出所有键
      keys he*   # 列出以 he 开头的键
      
  5. dbsize

    • 返回当前数据库中键的总量:
      dbsize  # 返回当前数据库中所有键的数量
      
  6. exists

    • 检查某个键是否存在,存在返回 1,不存在返回 0:
      exists name  # 检查 key=name 是否存在
      
  7. del

    • 删除指定的键:
      del name  # 删除 key=name
      
  8. expire

    • 设置键的过期时间(秒),过期后该键会被自动删除:
      expire name 20  # 设置 key=name 的过期时间为20秒
      
  9. ttl

    • 查询某个键的剩余存活时间(秒),如果该键没有设置过期时间,则返回 -1:
      ttl name  # 查询 key=name 的剩余过期时间
      

Redis 服务操作

  • 启动 Redis 服务:
    redis-server
    
  • 连接 Redis 客户端:
    redis-cli -p 6379  # 默认端口是6379
    
  • 如果 Redis 设置了密码,连接后需要认证:
    auth 12345  # 使用 auth 命令进行认证
    

注意事项

  • 不同编号的数据库之间的数据互不影响。
  • 使用 set 命令对同一个键多次赋值时,后面的值会覆盖前面的值。
  • keys * 虽然可以列出所有键,但如果数据库中的数据量非常大,不建议使用,因为效率较低。
  • 使用 dbsize 查询数据总量是非常高效的,底层通过计数器实现,不需要遍历所有数据。

5. Redis 五种常用数据类型及字符串类型课程笔记

课程简介

本节课介绍了 Redis 中五种常用的数据类型,包括字符串、哈希、列表、集合和有序集合。我们重点学习了字符串类型,它是最常用、最基础的数据类型。

Redis 五种数据类型

  1. 字符串类型(String)

    • Redis 中最常用的数据类型。
    • 可以存储字符串和数字,支持最大 512MB 的数据长度。
  2. 哈希类型(Hash)

    • 类似于字典,键值对的 value 本身是一个键值对结构。
  3. 列表类型(List)

    • 类似于数组,可以存储多个有序的值。
  4. 集合类型(Set)

    • 无序集合,元素不允许重复。
  5. 有序集合类型(ZSet)

    • 有序集合,集合中的每个元素关联一个分数,元素按照分数排序。

字符串类型(String)

  • 特点
    • 支持存储字符串或数字。
    • 字符串是 Redis 中最常用的数据类型。
    • 常用于存储简单的数据,如用户姓名、年龄等。

常用命令

  1. SET:设置键值对

    set key value
    

    例如:

    set name lily  # 设置 key=name, value=lily
    
  2. GET:获取键的值

    get key
    

    例如:

    get name  # 获取 key=name 的值
    
  3. MSET:一次设置多个键值对

    mset key1 value1 key2 value2 ...
    

    例如:

    mset name1 Kitty age1 20 birthday1 1999-01-12
    
  4. MGET:一次获取多个键的值

    mget key1 key2 ...
    

    例如:

    mget name1 age1 birthday1
    
  5. INCR:将键对应的值自增1

    incr key
    

    例如:

    incr age  # 将 age 的值自增1
    
  6. DECR:将键对应的值自减1

    decr key
    
  7. DEL:删除键

    del key
    

    例如:

    del name  # 删除 key=name
    

特殊用法

  • 计数器

    • 可以通过 INCRDECR 实现自增或自减操作,适用于计数场景。
    • 例如:incr age 将年龄自增1。
  • 批量操作

    • 通过 MSETMGET 可以一次操作多个键值对,提高效率。

Redis 哈希键值类型课程笔记

哈希键值类型的特点

  • 适用于存储结构化数据,例如用户信息、员工信息等。
  • 可以通过一个 key 存储多个属性及其对应的值,类似于 Java 中的 Map
  • 适用于保存包含多个属性的对象,简化 Redis 的数据存储结构,提高可用性。

常用命令

  1. HSET:设置哈希键的字段和值

    hset key field value
    

    例如:

    hset emp:1 name "张三"
    hset emp:1 age 35
    hset emp:1 birthday "1983-04-03"
    hset emp:1 height 178
    
  2. HGET:获取哈希键指定字段的值

    hget key field
    

    例如:

    hget emp:1 name  # 获取name字段的值
    
  3. HGETALL:获取哈希键的所有字段和值

    hgetall key
    

    例如:

    hgetall emp:1  # 获取一号员工所有属性和值
    
  4. HMSET:一次设置多个字段和值

    hmset key field1 value1 field2 value2 ...
    

    例如:

    hmset emp:2 name "Lisa" age 23 birthday "1990-05-03" height 165
    
  5. HDEL:删除哈希键的某个字段

    hdel key field
    

    例如:

    hdel emp:2 age  # 删除emp:2中的age字段
    
  6. HLEN:获取哈希键的字段数量

    hlen key
    

    例如:

    hlen emp:1  # 返回一号员工的属性数量
    
  7. HEXISTS:判断哈希键的字段是否存在

    hexists key field
    

    例如:

    hexists emp:1 name  # 判断name字段是否存在
    

Redis 列表类型课程笔记

列表类型特点

  • 元素类型:列表中的每个元素必须是字符串。
  • 有序性:按照插入顺序排序。
  • 长度:列表的最大长度为 2^32 - 1,约 40 亿个元素。
  • 常用场景:存储同一类型的数据集合,如学生信息列表、电脑设备列表等。

列表常用命令

  1. RPUSH:从列表右侧插入元素

    rpush key element1 element2 ...
    

    例如:

    rpush list_key C B A  # 在列表右侧依次插入 C、B、A
    
  2. LPUSH:从列表左侧插入元素

    lpush key element1 element2 ...
    

    例如:

    lpush list_key F E D  # 在列表左侧依次插入 F、E、D
    
  3. RPOP:从列表右侧弹出元素

    rpop key
    

    例如:

    rpop list_key  # 从列表右侧弹出一个元素
    
  4. LPOP:从列表左侧弹出元素

    lpop key
    

    例如:

    lpop list_key  # 从列表左侧弹出一个元素
    
  5. LRANGE:获取列表中指定范围的元素

    lrange key start stop
    

    例如:

    lrange list_key 0 -1  # 获取列表中的所有元素,-1 表示最后一个元素
    

Redis 集合类型(Set 和 ZSet)课程笔记

Set 和 ZSet 的特点

Set 集合特点

  • 无序:Set 集合中的元素没有顺序。
  • 唯一性:Set 集合中的元素都是唯一的,不能重复。
  • 常见场景:Set 常用于需要快速判断元素是否存在的场景,例如标签管理、用户角色管理等。

ZSet 集合特点

  • 有序:ZSet 集合中的元素通过设置的分数进行排序,默认按分数升序排列。
  • 唯一性:和 Set 一样,ZSet 中的元素也是唯一的,但可以为每个元素设置一个分数。
  • 常见场景:ZSet 常用于排行榜、带权重的元素存储等需要排序的场景。

Set 常用命令

  1. SADD:向集合添加元素

    sadd key element1 element2 ...
    

    例如:

    sadd set1 A B C
    
  2. SMEMBERS:获取集合中的所有元素

    smembers key
    

    例如:

    smembers set1  # 获取集合 set1 的所有元素
    
  3. SINTER:获取两个集合的交集

    sinter key1 key2
    

    例如:

    sinter set1 set2  # 获取 set1 和 set2 的交集
    
  4. SUNION:获取两个集合的并集

    sunion key1 key2
    

    例如:

    sunion set1 set2  # 获取 set1 和 set2 的并集
    
  5. SDIFF:获取两个集合的差集

    sdiff key1 key2
    

    例如:

    sdiff set1 set2  # 获取 set1 中有但 set2 中没有的元素
    

ZSet 常用命令

  1. ZADD:向有序集合添加元素及其分数

    zadd key score1 element1 score2 element2 ...
    

    例如:

    zadd zset1 100 A 101 B 99 C
    
  2. ZRANGE:按分数顺序获取有序集合中的元素

    zrange key start stop [WITHSCORES]
    

    例如:

    zrange zset1 0 -1 WITHSCORES  # 获取 zset1 中的所有元素及其分数
    
  3. ZRANGEBYSCORE:按分数范围获取有序集合中的元素

    zrangebyscore key min max
    

    例如:

    zrangebyscore zset1 100 103  # 获取分数在100到103之间的元素
    

package com.imooc.jedis;

import com.alibaba.fastjson.JSON;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class CacheSample {
    public CacheSample(){
        Jedis jedis = new Jedis("47.98.151.127");
        try {
            List<Goods> goodsList = new ArrayList<Goods>();
            goodsList.add(new Goods(8818, "红富士苹果", "", 3.5f));
            goodsList.add(new Goods(8819, "进口脐橙", "", 5f));
            goodsList.add(new Goods(8820, "进口香蕉", "", 25f));
            jedis.select(3);
            for (Goods goods : goodsList) {
                String json = JSON.toJSONString(goods);
                System.out.println(json);
                String key = "goods:" + goods.getGoodsId();
                jedis.set(key , json);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
    }

    public static void main(String[] args) {
        new CacheSample();
        System.out.printf("请输入要查询的商品编号:");
        String goodsId = new Scanner(System.in).next();
        Jedis jedis = new Jedis("47.98.151.127");
        try{
            jedis.select(3);
            String key = "goods:" + goodsId;
            if(jedis.exists(key)){
                String json = jedis.get(key);
                System.out.println(json);
                Goods g = JSON.parseObject(json, Goods.class);
                System.out.println(g.getGoodsName());
                System.out.println(g.getPrice());
            }else{
                System.out.println("您输入的商品编号不存在,请重新输入!");
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            jedis.close();
        }
    }
}

上一篇:猫头虎分享:什么是 ChatGPT 4o Canvas?


下一篇:python+appium+雷电模拟器安卓自动化及踩坑