Redis 基础详细介绍(Redis简单介绍,命令行客户端,Redis 命令,Java客户端)

发布于:2025-07-14 ⋅ 阅读:(19) ⋅ 点赞:(0)

1. Redis 简介

Redis(Remote Dictionary Server)是一个开源的内存数据库,遵守 BSD 协议,它提供了一个高性能的键值(key-value)存储系统,常用于缓存、消息队列、会话存储等应用场景。

1.1 特征

  • 丰富的数据类型:Redis 不仅仅支持简单的 key-value 类型的数据,还提供了 list、set、zset(有序集合)、hash 等数据结构的存储。这些数据类型可以更好地满足特定的业务需求,使得 Redis 可以用于更广泛的应用场景。

  • 高性能的读写能力:Redis 能读的速度是 110000次/s,写的速度是 81000次/s。这种高性能主要得益于 Redis 将数据存储在内存中,从而显著提高了数据的访问速度。

  • 原子性操作:Redis 的所有操作都是原子性的,这意味着操作要么完全执行,要么完全不执行。这种特性对于确保数据的一致性和完整性非常重要。

  • 持久化机制:Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,以便在系统重启后能够再次加载使用。这为 Redis 提供了数据安全性,确保数据不会因为系统故障而丢失。

  • 丰富的特性集:Redis 还支持 publish/subscribe(发布/订阅)模式、通知、key 过期等高级特性。这些特性使得 Redis 可以用于消息队列、实时数据分析等复杂的应用场景

  • 主从复制和高可用性:Redis 支持 master-slave 模式的数据备份,提供了数据的备份和主从复制功能,增强了数据的可用性和容错性。

  • 支持 Lua 脚本:Redis 支持使用 Lua 脚本来编写复杂的操作,这些脚本可以在服务器端执行,提供了更多的灵活性和强大的功能。

  • 单线程模型:尽管 Redis 是单线程的,但它通过高效的事件驱动模型来处理并发请求,确保了高性能和低延迟。

1.2 SQL 和 NOSQL 区别

Redis 属于 NOSQL 类型

  • 结构化:数据库表的字段的类型即长度都是限定好的。
  • SQL查询:SQL 查询语句格式是固定的无论 MySql 还是 Oracle
  • ACID:原子性,一致性,隔离性,持久性
  • BASE:不全部满足 ACID
  • 关联:数据表中的数据可以通过外键关联在一起

2. Redis 命令行客户端

Redis 安装完成后就自带了命令行客户端:redis-cli,使用方式如下:

// 先输入
redis-cli -h 127.0.0.1 -p 6379
// 回车后输入
auth 123456

其中常见的 options 有:

  • -h 127.0.0.1:指定要连接的 redis 节点的 IP 地址,默认是 127.0.0.1 (本机),也可以填写本机的 IP 地址
  • -p 6379:指定要连接的 redis 节点的端口,默认是 6379
  • -a 123456:指定 redis 的访问密码 (一般不这个,使用 auth 命令来输入密码)

3. Redis 数据结构介绍

4. Redis 命令

对于这些命令 Redis 都提供了帮助文档只要在你要使用的命令前面加入 help 即可

4.1 通用命令

  • KEYS

    查看符合模板的所有 key,不建议在生成环境设备上使用

    KEYS pattern
    
  • DEL

    删除一个指定的 Key

    DEL key [key ...]
    
  • EXISTS

    判断 Key 是否存在

    EXISTS key [key ...]
    
  • EXPIRE

    给一个 Key 设置有效期,有效期到了该 Key 自动删除

    EXPIRE key seconds
    
  • TTL

    查看一个 Key 剩余的有效期

    TTL key
    
  • hlep

    查看某个命令的使用方法

    help del
    

4.2 String类型命令

4.2.1 String类型分类

  • 字符串
  • 整形(Int)
  • 浮点型(Float)
4.2.2 常用命令
  • SET

    添加或者修改,指定键不存在则新增,否则修改

     set name jack
    
  • GET

    根据 key 获取 String 类型的 Value

    get name
    
  • MSET

    批量添加 String 类型的键值对

    mset key1 value1 key2 value2
    
  • MGET

    根据多个 Key 获取多个 Value

    mget key1 key2
    
  • INCR

    让一个整形的 key 的值自增 1

    incr age
    
  • INCRBY

    让一个整形 key 自增并指定步长

    incrby num 2
    
  • INCRBYFLOAT

    让一个浮点类型的值自增并指定步长

    incrbyfloat num 0.2
    
  • SETNX

    添加一个 String 类型的键值对前提是这个 Key 不存在,否则不执行

    setnx name jack
    
  • SETEX

    添加一个键值对,并指定有效日期。

    setex name 10 jack
    

4.3 Key的层级格式

在 Redis 没有类似于 MySQL 中 Table 的概念,我们如何区分不同类型 Key 呢?

比如我们需要存储商品信息和用户信息到 Redis 当中,此时他们的 Id 恰好都为 1。这样当我们要取数据时发现无法区分。此时我们可以给 Key 加上一个前缀加以区分。当然这前缀按规范要具有一定层次结构

4.4 Hash类型命令

该结构类似于 Java 的 HashMap

4.4.1 哈希类型结构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.4.2 常见命令

  • HSET key field value

    添加或者修改 Hash 类型,键为 key ,值的键为 field 的值为 Value

    hset user name zhansan 
    
  • HGET key field

    根据 key 获取 Hash 类型,键为 key ,值的键为 field 的值

    hget user name
    
  • HMSET

    批量添加 Hash 类型 Key 的 field 的值

    hset user name zhansan age 18
    
  • HMGET

    批量获取 Hash 类型,键为 key 的多个 field 的值

    hmget user name age
    
  • HGETALL

    获取一个 Hash 类型,键为 key 所有的键值对

    hgetall user
    
  • HKEYS

    获取一个 Hash 类型,键为 key 所有的键

    hkeys user
    
  • HVALS

    获取一个 Hash 类型,键为 key 所有的值

    hvals user
    
  • HINCRBY

    让一个 Hash 类型的 key 的 field 的值自增长指定步长

    hincrby user age 2
    
  • HSETNX

    添加一个 Hash 类型的 key 的 field 的值,前提是这个 field 不存在,否则不执行

    hsetnx user age 100
    

4.5 List类型

类似双端队列,查询慢,删除快,该数据类型可以根据方法,模拟栈,队列,阻塞队列的数据结构

4.5.1 常见命令

  • LPUSH key element

    向列表左侧插入一个或者多个元素

    lpush goods car food
    
  • RPUSH key element

    向列表右侧插入一个或者多个元素

    rpush goods car food
    
  • RPOP KEY [COUNT]

    将列表左侧元素弹出一个或者多个,没有则返回 nil

    lpop goods 2
    
  • RPOP KEY

    将列表右侧元素弹出一个或者多个,没有则返回 nil

    rpop goods 2
    
  • BLPOP 和 BRPOP [TimeOut]

    和 LPOP 和 RPOP 类似,只不过在当列表中没有元素的时候会等待指定时间,而不是返回nil,后面该功能会被充当缓冲队列

     Brpop user 10
    
  • LRANGE KEY STAR END

    返回一段角标内的所有元素

4.6 Set类型

无序,不重复,查询快,类似于 C++ 的 Unordered_Set

4.6.1 常见命令

  • SADD key member

    向指定 Key 的集合中插入一个或者多个元素

  • SREM key member

    将指定 Key 的集合中指定元素删除

  • SCARD key

    统计集合中的元素

  • SISMEMBER key member

    查询某个元素是否在集合当中

  • SMEMBERS key

    获取指定Key的集合中的所有元素

  • SINTER key1 key2

    获取键为 key1 和 key2 两个集合的交集

  • SDIFF key1 key2

    获取键为 key1 和 key2 两个集合的差集

  • SUNION key1 key2

    获取键为 key1 和 key2 两个集合的并集

4.7 SortedSet类型

可排序集合和 Java 中的 TreeSet 类似,但底层差距很大。SortedSet中的每个元素都带有一个score属性,可以基于 score 的值对集合进行排序,底层实现是 跳表 + hash表 。常被用于实现排行榜的业务。

4.7.1 常用命令

  • ZADD key score member

    添加一个或者多个元素,score 是加入元素的分数(排序依据),member 表示要加入的元素

  • ZREM key member

    删除指定元素

  • ZSCORE key member

    获取指定元素的分数

  • ZRANK key member

    获取指定元素的排名(默认升序排名,可以用 ZREVRANK 获取降序排名)

  • ZCARD key

    获取集合中的元素数量

  • ZCOUNT key min max

    统计 Score 值在 min 和 max 之间的元素个数

  • ZINCRBY key increment member

    让集合指定元素 member 自增,步长为指定的 increment 的值

  • ZRANGE key min max

    按照 Score 排序后,获取指定排名范围内的元素

  • ZRANGEBYSCORE key min max

    按照 Score 排序后,获取指定分数范围内的元素

  • ZDIFF,ZINTER,ZUNION

    求差集,求交集,求并集。

5. Java客户端

5.1 简介

Java的Redis客户端(如Jedis、Lettuce)通过封装Redis协议,允许Java应用与Redis服务器交互。它们提供直观的API执行数据操作,支持连接池、集群、哨兵等部署模式。其中Jedis轻量高效但线程不安全,需配合连接池使用;Lettuce基于Netty实现异步与线程安全Redisson专注分布式服务。开发者可根据性能、线程模型和功能需求灵活选用。

5.2 Jedis

5.2.1 简介

Jedis 是一款轻量级、同步阻塞的 Java Redis 客户端,通过直连模式与 Redis 服务器通信。其 API 直接映射 Redis 原生命令(如 set() 对应 SET 指令),学习成本低且稳定性强;但原生线程不安全(多线程需依赖连接池),适用于并发要求不高的传统项目或小型应用,是 Java 生态中最经典的 Redis 集成方案之一。

5.2.2 特点

  • 优点:
    Jedis 设计小巧,实现简洁,稳定性高。其最大优势在于 API 与 Redis 原生命令高度一致:方法名和参数直接对应官方文档指令。这使得开发者遇到不熟悉的操作时,无需额外学习客户端封装,直接查阅 Redis 命令文档即可快速上手,显著降低了学习成本。相比之下,某些客户端重命名 API 的做法虽意图简化,实则增加了额外的记忆负担。

  • 缺点:
    Jedis 采用直连模式且非线程安全。其核心问题在于:单个 Jedis 实例内的 RedisOutputStream (写流) 和 RedisInputStream (读流) 是共享的全局资源。当多个线程并发操作同一实例时,会争抢这些流资源,导致读写数据混乱(如数据错位、混合),而非 Redis 服务本身的数据安全问题。

5.2.3 Jedis 的使用

  • 引用依赖
<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>3.7.0</version>
</dependency>
  • 建立连接
private Jedis jedis;
@Before // 该注解,表示在所有你创键的测试方法前先执行,这里用于建立连接
public void setUp() throws Exception {
    jedis = new Jedis("192.168.195.132", 6379); //建立连接
    jedis.auth("123456"); //密码
    jedis.select(0); //选择库
}
  • 使用 Jedis
@Test
public void testString() {
    //命令名和 Redis 的一致 
    String s = jedis.set("name", "tom");
    String name = jedis.get("name");
}
  • 释放资源
@After // 该注解,表示在所有你创键的测试方法后执行,这里用于关闭连接
public void tearDown() throws Exception {
    // 如果在建立连接的时候抛出了异常,那么运行到这的时就会有空指针异常的风险
    if(jedis != null) {
        jedis.close();
    }
}

5.2.4 Jedis连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗。所以建议使用 Jedis 的连接池来代替 Jedis的直连方式。

public class JedisConnectionFactory {
    private static JedisPool jedisPool;
    static {
        //配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        //最大连接量,表示最多建立8个连接
        poolConfig.setMaxTotal(8); 
        //最大空闲连接,表示即便没有线程访问我这个池子,也会最多预备8个连接
        poolConfig.setMaxIdle(8); 
        //最小空闲连接,表示空闲连接存放一段时间后,会被自动释放,直到预备连接小于等于2个
        poolConfig.setMinIdle(2); 
        //最长等待时间,表示当连接池内没有空闲连接时,线程对多等多久后放弃等待
        poolConfig.setMaxWaitMillis(1000); 
        
        //建立连接
        jedisPool = new JedisPool(poolConfig,
                "192.168.195.132", 6379, 1000, "123456");
    }
   
    // 获取连接
    public static Jedis getJedis() {
         return jedisPool.getResource();
    }
}

5.3 SpringDataRedis

5.3.1 简介

  • Spring Data Redis 是 Spring 生态的 Redis 集成框架,内部整合来 Jedis 和 Lettuce。
  • 提供了RedisTemplate统一 API 来操作 Redis。
  • 简化数据操作(自动处理序列化/连接管理)
  • 支持事务、发布订阅、集群与哨兵模式,并天然适配 Spring 事务管理,显著降低 Java 应用访问 Redis 的复杂度,适用于需与 Spring 深度整合的中大型项目。

5.3.2 SpringDataRedis的使用

**SpringBoot 已经整合 SpringDataRedis,并且实现了自动装配,使用起来非常方便,**所以下面我们基于SpringBoot 来使用 SpringDataRedis

  • 引入依赖
<!--redis起步依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--连接池依赖-->
<!--无论是 Jedis 还是 Luttce,都是基于 commons-pool 来实现连接池的效果 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
  • 连接和连接池配置
spring:
  data:
    redis:
      host: 192.168.195.132 #连接的虚拟机的 IP 地址
      port: 6379 #端口号
      database: 0 #连接的数据库
      password: 123456 #密码
      lettuce:
        pool: #连接池的配置
          max-active: 8 #最大连接数
          max-idle: 8 #最大空闲连接数
          min-idle: 0 #最小空闲连接数
          max-wait: 100ms #最大等待时间
          #具体解释可以看 Jedis 配置连接池那一节
  • 测试代码
@SpringBootTest
class RedisDemoApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void stringTest() {
        redisTemplate.opsForValue().set("name", "虎哥");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println(name);
    }
}

5.3.3 RedisTemplated的缺点

RedisTemplate 可以存储任意类型的数据,原因是在存储之前会先把存储的数据序列化字节形式,默认采用的 JDK 序列化。但是得到的结果,可读性差,并且占用了更多的内存

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.3.3 解决方式

RedisTemplate 的缺点产生原因在于他默认的序列化方式不太合适,所以我们可以更改他的序列化方式即可解决这个问题。

存在的小问题以及解决办法

  • 但是这种方式还是存在一点点问题就是,他 Value 使用的是 Json 序列化器,当存入和获取的数据类型是对象是会自动序列化和反序列化,但是要实现自动反序列化,存入 Redis 的数据数据需要加一段额外的信息来记录该 Json 数据属于哪个对象,这样就造成了,内存的额外开销。
  • 解决方式也很简单,就是再一次跟换 Value 的序列化方式,采用和 Key 一样的 String 序列化器,但是后果就是,存入数据类型只能是 String 类型。但是没关系,只要当我们要存入对象时,就先将他转为 Json 字符串格式
  • 但是幸运的是我们不要自己再去修改,RedisTemplate 的 Value 的序列化方式了。这个别人已经写好了。Spring 提供了一个 StringRedisTemplate 类,他的 Key 和 Value 默认的序列化方式就是 String 序列化,省去了我们自己定义 RedisTemplate。

5.3.4 StringRedisTemplate

5.3.4.1 简介

为了节省空间我们并不会使用 Json 的序列化器来处理 value,而是统一的使用 String 的序列化器,要求只能存储String 类型的 key 和 value。当需要存储 Java 对象的时候,需手动完成对象序列化和反序列化

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.3.4.2 使用步骤

至于序列化工具,使用自己喜欢的就好,我这里使用的 FastJson

  • 导入依赖
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.7</version>
</dependency>
  • 代码演示
@Autowired
private StringRedisTemplate stringRedisTemplate;

@Test
void objectTest() {
    User user = new User("name", "虎哥");
    
    //手动序列化(object -> Json)
    String s = JSON.toJSONString(user);
    stringRedisTemplate.opsForValue().set("user:100", s);
    String s1 = stringRedisTemplate.opsForValue().get("user:100");
    
    //手动反序列化(Json -> object)
    User user1 = JSON.parseObject(s1, User.class);
    System.out.println(user1);
}


网站公告

今日签到

点亮在社区的每一天
去签到