搞定 Redis 不难:从安装到实战的保姆级教程

Redis 作为后端开发必学的缓存神器,非常有学习的必要,相信你看完一定有收获~~

在项目开发中,性能优化是绕不开的话题。而解决性能问题最常用的手段,就是加缓存。今天就来聊聊缓存界的扛把子 ------Redis,看看它到底有多好用,以及怎么上手。

一、Redis 到底是个啥

1. 先搞懂 Redis 是啥

Redis 是用 C 语言写的一款高性能键值对数据库,最牛的地方是数据存在内存里,所以读写速度快到飞起。官方说每秒能处理 10 万 + 的查询,这速度比传统数据库快太多了。

现在互联网项目里,Redis 几乎是标配的存储中间件。它的主要特点:

  • 数据存在内存,读写性能超强
  • 特别适合存热点数据(比如热门商品、新闻资讯)
  • 企业里用得非常多

Redis 默认端口是 6379,记一下,后面经常会用到。

官网在这里:redis.io,中文网:www.redis.net.cn/

这里插一嘴数据库分类:

关系型数据库(RDBMS):像 MySQL、Oracle 这些,数据存在表里,靠主键外键维护关系,优点是稳定安全

非关系型数据库(NoSql):不止 SQL 的意思,存储方式灵活,性能好。除了 Redis,还有 MongoDB(存文档的)、MemCached(也是缓存)

2. 安装 Redis

如果自己想装,用 docker 最方便,一条命令搞定:

css 复制代码
docker run -d --name redis --restart=always -p 6379:6379 redis --requirepass "123456"

这条命令会创建并启动 Redis 容器,要是本地没有镜像,会自动下载。

查看是否启动成功,看容器状态就行。

3. 用什么工具操作 Redis

总不能每次都进容器里敲命令吧?可以用图形化客户端,Another-Redis-Desktop-Manager,装上就能用。

安装好启动后,填好连接信息(地址、端口、密码),连上就能看到 Redis 里存的数据了,操作起来很方便。

4. 小结一下

Redis 就是个键值对数据库,数据放内存里,速度快,适合存热点数据。

数据库分关系型和非关系型,Redis 属于后者。

端口 6379 要记住。

启动关闭用 docker 命令:docker stop redis(关闭)、docker start redis(启动)

二、Redis 常用命令

Redis 存的是 key-value 结构,key 是字符串,value 有 5 种常用类型:字符串(string)、哈希(hash)、列表(list)、无序集合(set)、有序集合(zset)。

命令可以查 Redis 中文网,这里说常用的。

1. 操作 string 类型

string 是最基础的类型,常用命令:

命令 说明
SET key value 给 key 设值,要是 key 已经有值,就覆盖掉
GET key 取 key 的值
SETEX key seconds value 设值的同时,给 key 设个过期时间(秒)
SETNX key value 只有 key 不存在的时候才设值(分布式锁就靠这玩意)

还有个通用命令 del key,不管啥类型,想删 key 就用它。

2. 操作 hash 类型

hash 就像 Java 里的 HashMap,适合存对象。比如存用户信息,key 是用户 id,里面的 field 是 name、age 这些。

常用命令:

命令 说明
HSET key field value 给 hash 里的 field 设值
HGET key field 取 hash 里某个 field 的值
HKEYS key 取 hash 里所有的 field
HVALS key 取 hash 里所有的值
HDEL key field 删 hash 里的某个 field

3. 操作 list 类型

list 类似 LinkedList,是个双向链表,有序,元素能重复。

常用命令:

命令 说明
LPUSH key value1 [value2...] 从左边往列表里加元素,返回列表长度
RPOP key 从右边移除并返回最后一个元素
LRANGE key start stop 取列表里指定范围的元素
LLEN key 看列表有多少个元素

4. 操作 set 类型

set 类似 HashSet,无序,元素不能重复,查找快,还能做交集、并集这些操作。

常用命令:

命令 说明
SADD key member1 [member2...] 往集合里加元素
SMEMBERS key 取集合里所有元素
SCARD key 看集合有多少个元素
SINTER key1 [key2] 取两个集合的交集
SUNION key1 [key2] 取两个集合的并集

5. 操作 zset 类型

zset 是有序的 set,每个元素有个分数(score),按分数排序,适合做排行榜。

常用命令:

命令 说明
ZADD key score1 member1 [score2 member2...] 往有序集合里加元素,指定分数
ZRANGE key start stop [WITHSCORES] 按索引范围取元素,加 WITHSCORES 能看到分数
ZINCRBY key increment member 给某个元素的分数加增量
ZREM key member... 从有序集合里删元素

6. 通用命令

不管啥类型都能用的命令:

命令 说明
KEYS pattern 找符合模式的 key,* 代表任意字符,? 代表一个字符
EXISTS key 看看 key 存不存在
TYPE key 看看 key 的值是啥类型
DEL key 删 key,不管啥类型都能删

7. 小结一下

Redis 存的是键值对,key 是字符串,value 有 5 种类型:

  • string:字符串,最基础的
  • hash:哈希表,适合存对象
  • list:链表,适合做队列
  • set:无序集合,适合去重、做集合运算
  • zset:有序集合,适合做排行榜

记几个常用操作就行,用的时候查文档也来得及。

三、SpringDataRedis

Java 项目里怎么操作 Redis 呢?就像用 JDBC 操作 MySQL 一样,得用 Redis 的 Java 客户端。常用的有 Jedis、Lettuce,而 Spring 给我们封装了 SpringDataRedis,用起来更方便,尤其是在 Spring Boot 项目里。

1. 简单介绍

Spring Data Redis 是 Spring 家族的一员,封装了底层的 Redis 客户端,配置一下就能用。

Spring Boot 里有对应的 starter,maven 依赖长这样(咱们项目的 common 模块里已经有了,直接用):

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

里面有个 RedisTemplate 类,特别好用,把各种操作分类了:

  • 操作 string:redisTemplate.opsForValue ()
  • 操作 hash:redisTemplate.opsForHash ()
  • 操作 set:redisTemplate.opsForSet ()
  • 操作 zset:redisTemplate.opsForZSet ()
  • 操作 list:redisTemplate.opsForList ()
  • 通用操作:直接用 redisTemplate

2. 准备环境

在 zzyl-admin 模块的 pom.xml 里加个单元测试的依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

然后在 com.zzyl.redis 包里建个测试类,注入 RedisTemplate:

kotlin 复制代码
package com.zzyl.redis;
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.RedisTemplate;
@SpringBootTest
public class RedisTest {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Test
    public void test() {
        System.out.println(redisTemplate);
    }
}

3. 常用操作示例

csharp 复制代码
/**
 * 操作字符串
 */
@Test
public void testString() {
    // 普通设值
    redisTemplate.opsForValue().set("name", "张三");
    System.out.println(redisTemplate.opsForValue().get("name"));
    // 设值并加过期时间(20秒)
    redisTemplate.opsForValue().set("token", "123qweasd",20, TimeUnit.SECONDS);
    System.out.println(redisTemplate.opsForValue().get("token"));
    // setnx,key不存在才设值,返回true,否则false
    System.out.println(redisTemplate.opsForValue().setIfAbsent("lock", "09876", 5, TimeUnit.MINUTES));
    System.out.println(redisTemplate.opsForValue().setIfAbsent("lock", "34567", 5, TimeUnit.MINUTES));
}
/**
 * 操作哈希
 */
@Test
public void testHash() {
    // 存哈希数据,大key是user,小key是name和age
    redisTemplate.opsForHash().put("user", "name", "张三");
    redisTemplate.opsForHash().put("user", "age", "30");
    // 取哈希里的某个值
    System.out.println(redisTemplate.opsForHash().get("user", "name"));
    // 取所有小key
    Set<Object> keys = redisTemplate.opsForHash().keys("user");
    System.out.println(keys);
    // 取所有值
    List<Object> values = redisTemplate.opsForHash().values("user");
    System.out.println(values);
    // 删某个小key
    redisTemplate.opsForHash().delete("user", "age");
}
/**
 * 操作列表
 */
@Test
public void testList() {
    // 从左边加多个值,变成[a,b,c]
    redisTemplate.opsForList().leftPushAll("mylist", "a", "b", "c");
    // 再从左边加个d,变成[d,a,b,c]
    redisTemplate.opsForList().leftPush("mylist", "d");
    // 取列表里的数据
    System.out.println(redisTemplate.opsForList().range("mylist", 0, -1));
    // 从左边弹出一个元素
    System.out.println(redisTemplate.opsForList().leftPop("mylist"));
    // 看列表长度
    System.out.println(redisTemplate.opsForList().size("mylist"));
}
/**
 * 操作集合
 */
@Test
public void testSet() {
    // 往两个集合里加元素
    redisTemplate.opsForSet().add("myset1", "a", "b", "c", "d");
    redisTemplate.opsForSet().add("myset2", "a", "b", "x", "y");
    // 取集合所有元素
    Set<String> members = redisTemplate.opsForSet().members("myset1");
    System.out.println(members);
    // 看集合大小
    long size = redisTemplate.opsForSet().size("myset1");
    System.out.println(size);
    // 取交集
    Set<String> intersection = redisTemplate.opsForSet().intersect("myset1", "myset2");
    System.out.println("交集:" + intersection);
    // 取并集
    Set<String> union = redisTemplate.opsForSet().union("myset1", "myset2");
    System.out.println("并集:" + union);
}
/**
 * 操作有序集合
 */
@Test
public void testZset() {
    // 加元素,指定分数
    redisTemplate.opsForZSet().add("myzset", "a", 1);
    redisTemplate.opsForZSet().add("myzset", "b", 10);
    redisTemplate.opsForZSet().add("myzset", "c", 20);
    // 取所有元素
    Set<String> members = redisTemplate.opsForZSet().range("myzset", 0, -1);
    System.out.println(members);
    // 给a的分数加10
    redisTemplate.opsForZSet().incrementScore("myzset", "a", 10);
    // 删a和b
    redisTemplate.opsForZSet().remove("myzset", "a", "b");
}
/**
 * 通用命令
 */
@Test
public void testCommon() {
    // 取所有key
    Set<String> keys = redisTemplate.keys("*");
    System.out.println(keys);
    
    // 看key是否存在
    Boolean isName = redisTemplate.hasKey("name");
    System.out.println(isName);
    
    // 看key的类型
    DataType type = redisTemplate.type("myzset");
    System.out.println(type.name());
    
    // 删key
    redisTemplate.delete("myzset");
}

4. 小结一下

Java 里用 SpringDataRedis 操作 Redis,步骤很简单:

  1. 加依赖(项目里已经有了)
  1. 注入 RedisTemplate 对象
  1. 用对应的方法操作不同类型的数据

记住各个类型对应的方法前缀:

  • string:opsForValue()
  • hash:opsForHash()
  • list:opsForList()
  • set:opsForSet()
  • zset:opsForZSet()

四、若依框架里的缓存使用

咱们用的若依框架,就是用 Redis 做缓存的。

核心的配置在 zzyl-framework 模块的 com.zzyl.framework.config.RedisConfig 类里。这个类主要是开启缓存注解,还有配置对象的序列化和反序列化(就是把对象转成能存的格式,取的时候再转回来)。

还有个 com.zzyl.common.core.redis.RedisCache 类,封装了常用的 Redis 操作方法,开发的时候直接用这个类就行,很方便。

五、用缓存优化项目

缓存就是高速的临时存储,用好缓存能大大提高系统性能。

1. 哪些数据适合放缓存

  • 经常被访问,但不怎么变的数据:像用户信息、系统配置、数据字典这些
  • 热门内容:热门文章、视频、评论,访问量特别大的
  • 临时数据:比如验证码,存内存里快,还能设过期时间自动删
  • 小数据但访问频繁:哪怕数据不大,只要经常被查,放缓存里也能提高性能

总之,缓存不是万能的,但用好它,系统性能能上一个大台阶。

觉得有用的话,点赞收藏就是对硬核干货最好的认可~

相关推荐
欧哈东哥9 分钟前
【C++】标准库中用于组合多个值的数据结构pair、tuple、array...
java·数据结构·c++
python_13613 分钟前
web请求和响应
java·spring·github
柏油31 分钟前
可视化 MySQL binlog 监听方案
数据库·后端·mysql
舒一笑1 小时前
Started TttttApplication in 0.257 seconds (没有 Web 依赖导致 JVM 正常退出)
jvm·spring boot·后端
M1A11 小时前
Java Enum 类:优雅的常量定义与管理方式(深度解析)
后端
AAA修煤气灶刘哥2 小时前
别再懵了!Spring、Spring Boot、Spring MVC 的区别,一篇讲透
后端·面试
ciku2 小时前
Spring AI Starter和文档解读
java·人工智能·spring
柏油2 小时前
MySQL 字符集 utf8 与 utf8mb4
数据库·后端·mysql