【从零开始学Redis | 第一篇】Redis常用数据结构与基础

目录

前言

一、今日完结任务

二、今日核心知识点总结

[1. NoSQL与关系型数据库对比](#1. NoSQL与关系型数据库对比)

[2. Redis核心特性](#2. Redis核心特性)

[3. 为什么使用Redis?](#3. 为什么使用Redis?)

三、遇到的问题:连接Redis服务失败

[1. 问题描述](#1. 问题描述)

[2. 问题分析](#2. 问题分析)

[3. 解决方案](#3. 解决方案)

四、今日实战收获

[1. Redis五种数据结构实战](#1. Redis五种数据结构实战)

[1.1 String(字符串类型)](#1.1 String(字符串类型))

[1.2 Hash(哈希类型)](#1.2 Hash(哈希类型))

[1.3 List(列表类型)](#1.3 List(列表类型))

[1.4 Set(集合类型)](#1.4 Set(集合类型))

[1.5 SortedSet(有序集合)](#1.5 SortedSet(有序集合))

[2. Redis通用命令](#2. Redis通用命令)

[3. Redis桌面客户端使用](#3. Redis桌面客户端使用)

[4. StringRedisTemplate实战](#4. StringRedisTemplate实战)

[4.1 SpringBoot项目集成](#4.1 SpringBoot项目集成)

[4.2 基本使用示例](#4.2 基本使用示例)

[4.3 对象存储的最佳实践](#4.3 对象存储的最佳实践)

[4.4 事务操作](#4.4 事务操作)

五、小知识点总结

[1. Redis键的命名规范](#1. Redis键的命名规范)

[2. 数据库选择](#2. 数据库选择)

[3. 数据类型选择策略](#3. 数据类型选择策略)

[4. 命令使用技巧](#4. 命令使用技巧)

[5. StringRedisTemplate优势](#5. StringRedisTemplate优势)

[6. 常用操作接口](#6. 常用操作接口)

总结


前言

时隔一周,今天我开始学习企业级项目中必不可少的缓存中间件------Redis。在前几天完成了苍穹外卖项目后,我深刻体会到数据访问性能的重要性,而Redis作为高性能的内存数据库,正是解决高并发访问、数据缓存等问题的利器。

今天主要学习Redis的基础概念、安装部署以及基本数据结构操作,为后续在实际项目中应用Redis打下坚实基础。


一、今日完结任务

  1. ✅ 学习NoSQL数据库概念及其与关系型数据库的区别

  2. ✅ 了解Redis的特点和应用场景

  3. ✅ 掌握Windows环境下Redis的安装与配置

  4. ✅ 学习Redis的5种基本数据结构及其常用命令

  5. ✅ 使用Redis可视化客户端进行基本操作


二、今日核心知识点总结

1. NoSQL与关系型数据库对比

NoSQL特点:

  • 非结构化:数据格式灵活,没有严格的表结构约束

  • 无关联性:数据间没有外键关联,关系维护依赖业务逻辑

  • 高性能 :基于内存操作,读写速度快,适合高并发场景

  • 可扩展性强:支持水平扩展,适合海量数据存储

核心对比:

对比维度 关系型数据库 NoSQL数据库
数据结构 结构化,表格式 非结构化,灵活
数据关联 表间关联(外键) 无关联或业务维护
查询语言 SQL(标准统一) 各数据库不同
事务支持 ACID原则 基本一致或不支持
存储方式 磁盘存储,有IO 内存为主,速度快
扩展方式 垂直扩展(主从) 水平扩展(分片)

2. Redis核心特性

  • 内存存储:数据主要存储在内存中,读写性能极高

  • 单线程模型:命令执行具备原子性,避免线程安全问题

  • 丰富的数据结构:支持String、Hash、List、Set、SortedSet等

  • 持久化支持:可将内存数据保存到磁盘,防止数据丢失

  • 高可用性:支持主从复制、哨兵模式、集群部署

  • 多语言客户端:Java、Python、Go等主流语言都支持

3. 为什么使用Redis?

主要是因为 Redis 具备**「高性能」「高并发」**两种特性。

1. Redis 具备高性能

假如用户第一次访问 MySQL 中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据缓存在 Redis 中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了,操作 Redis 缓存就是直接操作内存,所以速度相当

2. Redis 具备高并发

单台设备的 Redis 的 QPS(Query Per Second,每秒钟处理完请求的次数) 是 MySQL 的 10 倍,Redis 单机的QPS 能轻松破 10w,而 MySQL 单机的 QPS 很难破 1w。

所以,直接访问 Redis 能够承受的请求是远远大于直接访问 MySQL 的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。


三、遇到的问题:连接Redis服务失败

1. 问题描述

在Windows中安装Redis后,使用Redis客户端连接时出现以下错误:

复制代码
Could not connect to Redis at 127.0.0.1:6379: Connection refused

2. 问题分析

  1. Redis服务未启动

  2. 防火墙阻止了6379端口

  3. Redis配置绑定了特定IP地址(默认只允许本地访问)

3. 解决方案

步骤1:保证Redis在后台运行

步骤2:修改Redis配置文件

编辑redis.conf文件,关键配置修改:

bash 复制代码
# 允许所有IP访问(生产环境需谨慎)
bind 0.0.0.0
# 以守护进程方式运行
daemonize yes
# 设置密码(可选)
requirepass 123456

步骤3:重启Redis服务

在Redis安装目录下启动cmd输入

复制代码
# 指定配置文件启动
redis-server.exe redis.windows.conf

步骤4:测试连接

复制代码
# 使用密码连接
redis-cli -h 127.0.0.1 -p 6379 -a 123456
# 测试连接
ping  # 应返回PONG

四、今日实战收获

1. Redis五种数据结构实战

1.1 String(字符串类型)

String类型,也就是字符串类型,是Redis中最简单的存储类型。

适用场景:缓存、计数器、分布式锁

bash 复制代码
# 设置值
SET name "张三"
# 获取值
GET name
# 设置过期时间(10秒)
SETEX token 10 "abc123"
# 数值递增
INCR views  # 自增1
INCRBY views 5  # 自增5
1.2 Hash(哈希类型)

Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构。

适用场景:存储对象信息,如用户信息、商品详情

bash 复制代码
# 设置单个字段
HSET user:1001 name "李四"
HSET user:1001 age 25
# 批量设置字段
HMSET user:1002 name "王五" age 30 city "北京"
# 获取所有字段
HGETALL user:1001
# 获取指定字段
HGET user:1001 name
# 字段递增
HINCRBY user:1001 age 1
1.3 List(列表类型)

Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。

适用场景:消息队列、最新列表、历史记录

bash 复制代码
# 左侧插入
LPUSH messages "msg1" "msg2"
# 右侧插入
RPUSH messages "msg3"
# 左侧弹出
LPOP messages
# 右侧弹出
RPOP messages
# 获取范围元素
LRANGE messages 0 2
1.4 Set(集合类型)

Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的**HashMap。**因为也是一个hash表,因此具备与HashSet类似的特征:

适用场景:标签、共同好友、随机推荐

bash 复制代码
# 添加元素
SADD tags "Java" "Redis" "MySQL"
# 查看所有元素
SMEMBERS tags
# 删除元素
SREM tags "MySQL"
# 集合运算
SADD set1 "A" "B" "C"
SADD set2 "B" "C" "D"
# 交集
SINTER set1 set2  # 返回: B C
# 并集
SUNION set1 set2  # 返回: A B C D
# 差集
SDIFF set1 set2   # 返回: A
1.5 SortedSet(有序集合)

Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。

适用场景:排行榜、带权重的队列

bash 复制代码
# 添加带分值的元素
ZADD leaderboard 100 "张三" 95 "李四" 85 "王五"
# 按分值升序获取(0到2名)
ZRANGE leaderboard 0 2
# 按分值降序获取(0到2名)
ZREVRANGE leaderboard 0 2
# 获取元素排名(从0开始)
ZRANK leaderboard "李四"
# 获取元素分值
ZSCORE leaderboard "张三"

2. Redis通用命令

bash 复制代码
# 查看所有key(生产环境慎用)
KEYS *
# 查看以user开头的key
KEYS user:*
# 判断key是否存在
EXISTS user:1001
# 设置key过期时间(秒)
EXPIRE token 3600
# 查看key剩余生存时间
TTL token
# 删除key
DEL user:1001
# 选择数据库(0-15)
SELECT 1

3. Redis桌面客户端使用

安装了Another Redis Desktop Manager,通过图形界面:

  • 直观查看所有key和value

  • 支持多种数据结构可视化展示

  • 可直接编辑、删除数据

  • 支持批量操作和导入导出

4. StringRedisTemplate实战

4.1 SpringBoot项目集成

Maven依赖:

XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

配置文件application.yml:

XML 复制代码
spring:
  redis:
    host: localhost
    port: 6379
    password: 123456
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 100ms
4.2 基本使用示例
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class RedisService {
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    // 1. String类型操作
    public void stringOperations() {
        // 设置值
        stringRedisTemplate.opsForValue().set("username", "张三");
        
        // 获取值
        String username = stringRedisTemplate.opsForValue().get("username");
        
        // 设置过期时间
        stringRedisTemplate.opsForValue().set("token", "abc123", 3600, TimeUnit.SECONDS);
        
        // 递增操作
        stringRedisTemplate.opsForValue().increment("pageView");
        stringRedisTemplate.opsForValue().increment("pageView", 5);
    }
    
    // 2. Hash类型操作
    public void hashOperations() {
        // 设置hash字段
        stringRedisTemplate.opsForHash().put("user:1001", "name", "李四");
        stringRedisTemplate.opsForHash().put("user:1001", "age", "25");
        
        // 获取hash字段
        String name = (String) stringRedisTemplate.opsForHash().get("user:1001", "name");
        
        // 获取所有字段
        Map<Object, Object> user = stringRedisTemplate.opsForHash().entries("user:1001");
    }
    
    // 3. List类型操作
    public void listOperations() {
        // 左侧插入
        stringRedisTemplate.opsForList().leftPush("messages", "Hello");
        stringRedisTemplate.opsForList().leftPush("messages", "World");
        
        // 获取范围元素
        List<String> messages = stringRedisTemplate.opsForList().range("messages", 0, -1);
    }
    
    // 4. Set类型操作
    public void setOperations() {
        // 添加元素
        stringRedisTemplate.opsForSet().add("tags", "Java", "Redis", "MySQL");
        
        // 获取所有元素
        Set<String> tags = stringRedisTemplate.opsForSet().members("tags");
    }
}
4.3 对象存储的最佳实践

使用JSON序列化存储对象:

java 复制代码
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@Service
public class UserService {
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    // 存储对象(手动序列化为JSON)
    public void saveUser(User user) throws JsonProcessingException {
        String userJson = objectMapper.writeValueAsString(user);
        String key = "user:" + user.getId();
        stringRedisTemplate.opsForValue().set(key, userJson);
        
        // 可以设置过期时间
        stringRedisTemplate.expire(key, 1, TimeUnit.HOURS);
    }
    
    // 获取对象(手动反序列化)
    public User getUser(Long userId) throws JsonProcessingException {
        String key = "user:" + userId;
        String userJson = stringRedisTemplate.opsForValue().get(key);
        
        if (userJson != null) {
            return objectMapper.readValue(userJson, User.class);
        }
        return null;
    }
    
    // 存储对象到Hash
    public void saveUserToHash(User user) {
        String key = "user:hash:" + user.getId();
        Map<String, String> userMap = new HashMap<>();
        userMap.put("id", user.getId().toString());
        userMap.put("name", user.getName());
        userMap.put("age", user.getAge().toString());
        userMap.put("email", user.getEmail());
        
        stringRedisTemplate.opsForHash().putAll(key, userMap);
    }
}
4.4 事务操作
java 复制代码
public void transactionalOperations() {
    // 使用SessionCallback执行事务
    stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
        @Override
        public List<Object> execute(RedisOperations operations) throws DataAccessException {
            operations.multi(); // 开启事务
            
            operations.opsForValue().set("key1", "value1");
            operations.opsForValue().set("key2", "value2");
            operations.opsForValue().increment("counter");
            
            return operations.exec(); // 执行事务
        }
    });
}

五、小知识点总结

1. Redis键的命名规范

bash 复制代码
# 使用冒号分隔形成层级结构
# 项目名:数据类型:ID
user:1001:info
product:2001:detail
order:3001:items

2. 数据库选择

  • Redis默认有16个数据库(0-15)

  • 不同数据库完全隔离,key可以重复

  • 生产环境建议使用默认的0号库

3. 数据类型选择策略

  • String:简单KV,如缓存、计数器

  • Hash对象类型,如用户信息

  • List有序可重复,如消息队列

  • Set无序不重复,如标签系统

  • SortedSet有序不重复,如排行榜

4. 命令使用技巧

  • 批量操作:使用MSET、HMSET、SADD等批量命令,减少网络开销

  • 管道技术:一次性发送多个命令,提升执行效率

  • 原子操作 :INCR、DECR等命令是原子性的,适合计数器场景

5. StringRedisTemplate优势

  1. 避免序列化问题:不存储类信息,不会因类路径变化导致反序列化失败

  2. 跨语言兼容:存储的是JSON字符串,其他语言也可以读取

  3. 便于调试:Redis中可以直接查看存储的内容

  4. 节省内存:不存储额外的类信息,内存占用更小

6. 常用操作接口

总结

今天系统地学习了Redis的基础知识,从NoSQL概念到Redis具体安装配置,再到5种核心数据结构的操作命令。通过实践操作,我深刻体会到Redis作为内存数据库(缓存)的独特优势:

  1. 性能卓越:内存操作带来的毫秒级响应,完全满足高并发场景需求

  2. 数据结构丰富:不仅仅是简单的KV存储,多种数据结构能灵活应对不同业务场景

  3. 操作原子性:单线程模型保证了命令执行的原子性,简化了并发控制

  4. 部署灵活:支持多种集群模式,能满足不同规模的业务需求


相关推荐
阿猿收手吧!2 小时前
【C++】volatile与线程安全:核心区别解析
java·c++·安全
Hui Baby2 小时前
Java SPI 与 Spring SPI
java·python·spring
我能坚持多久2 小时前
D22—C语言预处理详解:从宏定义到条件编译
c语言·开发语言
小猪咪piggy2 小时前
【Python】(3) 函数
开发语言·python
青岑CTF2 小时前
攻防世界-Php_rce-胎教版wp
开发语言·安全·web安全·网络安全·php
摇滚侠2 小时前
Maven 教程,Maven 安装及使用,5 小时上手 Maven 又快又稳
java·maven
倔强菜鸟2 小时前
2026.2.2--Jenkins的基本使用
java·运维·jenkins
hai74252 小时前
在 Eclipse 的 JSP 项目中引入 MySQL 驱动
java·mysql·eclipse
初次见面我叫泰隆2 小时前
Qt——4、Qt窗口
开发语言·qt·客户端开发