前言:

推荐免费Redis基础讲解视频:【狂神说Java】Redis最新超详细版教程通俗易懂_哔哩哔哩_bilibili

通过Jedis操作Redis

jedis是Redis官方推荐的Java连接开发工具,使用Java操作Redis中间键;

简单测试

  1. 新建一个空的IDEA项目

  2. 新建Maven的Module为redis-01-jedis

  3. 在pom引入依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!--    引入jedis-->
    <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
    </dependency>
    <!-- fastjson-->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
    </dependency>
  4. 编码测试(本地)

    连接Redis

    打开Windows下安装的Redis中的redis-server

    操作命令

    在项目中新建类TestPing

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package com.joker.test;

    import redis.clients.jedis.Jedis;

    /**
    * @author Joker大雄
    * @data 2022/9/17 - 10:12
    **/
    public class TestPing {
    public static void main(String[] args) {
    // 1. new Jedis,使用本地redis连接
    Jedis jedis = new Jedis("127.0.0.1",6379);
    // jedis有redis所有指令
    System.out.println(jedis.ping());
    // 关闭连接
    jedis.close();
    }
    }

    运行结果

    1
    2
    3
    PONG

    Process finished with exit code 0
  5. 连接测试(远程)

    配置redis.conf

    • 设置访问redis的密码:requirepass 要设置密码

    • 重启redis-server服务,进入redis后要先验证密码,然后ping一下看有没有配置成功

      1
      2
      3
      127.0.0.1:6379>auth 密码
      127.0.0.1:6379>ping
      PONG

    操作命令

    在项目中新建类TestPing1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.joker.test;

    import redis.clients.jedis.Jedis;

    /**
    * @author Joker大雄
    * @data 2022/9/17 - 10:12
    **/
    public class TestPing1 {
    public static void main(String[] args) {
    // 1. new Jedis,使用远程连接redis
    Jedis jedis = new Jedis("你服务器IP",6379);
    // 2,idea访问时添加auth密码
    jedis.auth("redis.conf中配置的redis的密码");
    // jedis有redis所有指令
    System.out.println(jedis.ping());
    // 关闭连接
    jedis.close();
    }
    }

    运行结果

    1
    2
    3
    PONG

    Process finished with exit code 0

通过Jedis再次理解事务

  1. 新建一个类TXDemo

  2. 编写事务的方法(正常执行)

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    package com.joker.test;

    import com.alibaba.fastjson.JSONObject;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.Transaction;

    /**
    * @author Joker大雄
    * @data 2022/9/17 - 10:23
    **/
    public class TXDemo {
    public static void main(String[] args) {
    Jedis jedis = new Jedis("127.0.0.1", 6379);
    jedis.flushDB();// 清空数据
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("hello","world");
    jsonObject.put("name","jokerdig");
    String str = jsonObject.toJSONString();
    // 测试事务
    // 开启事务
    Transaction multi = jedis.multi();

    try {
    multi.set("user1",str);
    multi.set("user2",str);
    multi.exec(); // 执行事务
    } catch (Exception e) {
    multi.discard();// 放弃事务,抛出异常
    e.printStackTrace();
    } finally{
    System.out.println(jedis.get("user1"));
    System.out.println(jedis.get("user2"));
    // 关闭连接
    jedis.close();
    }
    }
    }

    运行结果

    1
    2
    3
    4
    {"name":"jokerdig","hello":"world"}
    {"name":"jokerdig","hello":"world"}

    Process finished with exit code 0
  3. 编写事务的方法(不正常执行)

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    package com.joker.test;

    import com.alibaba.fastjson.JSONObject;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.Transaction;

    /**
    * @author Joker大雄
    * @data 2022/9/17 - 10:23
    **/
    public class TXDemo {
    public static void main(String[] args) {
    Jedis jedis = new Jedis("127.0.0.1", 6379);
    jedis.flushDB();// 清空数据
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("hello","world");
    jsonObject.put("name","jokerdig");
    String str = jsonObject.toJSONString();
    // 测试事务
    // 开启事务
    Transaction multi = jedis.multi();

    try {
    multi.set("user1",str);
    multi.set("user2",str);
    int i = 1/0; // 异常代码
    multi.exec(); // 执行事务
    } catch (Exception e) {
    multi.discard();// 放弃事务,抛出异常
    e.printStackTrace();
    } finally{
    System.out.println(jedis.get("user1"));
    System.out.println(jedis.get("user2"));
    // 关闭连接
    jedis.close();
    }
    }
    }

    运行结果

    1
    2
    3
    4
    5
    6
    java.lang.ArithmeticException: / by zero
    at com.joker.test.TXDemo.main(TXDemo.java:27)
    null
    null

    Process finished with exit code 0

SpringBoot集成Redis

整合数据都在Spring Data中

在SpringBoot2.x之后,原来使用的jedis被替换为lettuce

jedis:采用直连,多个线程操作不安全,若避免不安全,可以使用jedis pool连接池;BIO

lecttuce:采用netty,实例可以在多个线程中共享,不存在线程不安全问题,减少线程数据;NIO模式

  1. 新建SpringBoot的Module为redis-02-springboot

  2. 勾选开发工具所有选项,及Spring WebSpring Data Redis

  3. pom依赖

    1
    2
    3
    4
    5
    <!--        redis-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
  4. 测试

    引入application.properties配置

    1
    2
    3
    # 配置
    spring.redis.host=127.0.0.1
    spring.redis.port= 6379

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    package com.jokerdig;

    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.connection.RedisConnection;
    import org.springframework.data.redis.core.RedisTemplate;

    @SpringBootTest
    class Redis02SpringbootApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
    //redisTemplate
    // opsForValue 操作字符串
    // opsForList 操作list
    // opsForSet
    // opsForHash
    // opsForZSet
    // opsForGeo
    // opsForHyperLogLog
    // 获取连接
    // RedisConnection conn = redisTemplate.getConnectionFactory().getConnection();
    // conn.flushDb();
    // conn.flushAll();
    redisTemplate.opsForValue().set("mykey","jokerdig");
    System.out.println(redisTemplate.opsForValue().get("mykey"));
    }
    }

    运行结果

    1
    jokerdig

自定义RedisTemplate

  1. config包下新建RedisConfig.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    package com.jokerdig.config;

    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;

    import java.rmi.UnknownHostException;

    /**
    * @author Joker大雄
    * @data 2022/9/17 - 11:49
    **/
    @Configuration
    public class RedisConfig {
    // 自定义redistemplate
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory)
    throws UnknownHostException{
    RedisTemplate<String,Object> template = new RedisTemplate<>();
    template.setConnectionFactory(factory);
    // 配置具体序列化
    Jackson2JsonRedisSerializer jrs = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator());
    objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
    jrs.setObjectMapper(objectMapper);
    StringRedisSerializer serializer = new StringRedisSerializer();
    // key采用String序列化方式
    template.setKeySerializer(serializer);
    // hash的key也采用String序列化
    template.setHashKeySerializer(serializer);
    // value序列化采用jackson
    template.setValueSerializer(jrs);
    template.afterPropertiesSet();
    return template;
    }
    }
  2. pojo包下新建User.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.jokerdig.pojo;

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.springframework.stereotype.Component;

    import java.io.Serializable;

    /**
    * @author Joker大雄
    * @data 2022/9/17 - 12:19
    **/
    @Component
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User implements Serializable {
    private String name;
    private int age;
    }
  3. 在测试类进行测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    package com.jokerdig;

    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.jokerdig.pojo.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.RedisTemplate;

    @SpringBootTest
    class Redis02SpringbootApplicationTests {

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;
    @Test
    void test() throws JsonProcessingException {
    // 真实开发传递一般都使用json
    User user = new User("Joker大雄",18);
    String jsonUser = new ObjectMapper().writeValueAsString(user);
    redisTemplate.opsForValue().set("user",jsonUser);
    System.out.println(redisTemplate.opsForValue().get("user"));
    }
    }
  4. 运行结果

    1
    {"name":"Joker大雄","age":18}

    redis客户端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 自定义序列化前,显示乱码
    127.0.0.1:6379> keys *
    1) "\xac\xed\x00\x05t\x00\x04user"
    # 清空数据库
    127.0.0.1:6379> flushdb
    # 自定义序列化后,显示正常
    127.0.0.1:6379> keys *
    1) "user"
    127.0.0.1:6379>

Redis配置文件详解

启动Redis,就是通过Redis配置文件

单位

units单位对大小写不敏感

1
2
3
4
5
6
7
8
9
10
11
# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.

包含

INCLUDES

1
2
3
4
5
6
################################## INCLUDES ###################################
#
# include /path/to/local.conf
# include /path/to/other.conf
# include /path/to/fragments/*.conf
#

网络

NETWORK

1
2
3
4
5
6
7
8
9
10
################################## NETWORK #####################################
# 绑定IP
bind 127.0.0.1 -::1
# 是否受保护
protected-mode yes
# 端口号
port 6379
# tcp连接
tcp-backlog 511
tcp-keepalive 300

通用

GENERAL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
################################# GENERAL #####################################
# 以守护进程方式运行,默认为no,我们手动设置为yes
daemonize yes
# 如果以后台方式运行,就要指定一个pid文件
pidfile /var/run/redis_6379.pid
# 日志
# debut
# verbose
# notice
# warning
loglevel notice
# 日志文件名
logfile ""
# 数据数量 默认16
databases 16
# 是否显示redis logo
always-show-logo no

set-proc-title yes
proc-title-template "{title} {listen-addr} {server-mode}"

持久化

SNAPSHOTTING

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
################################ SNAPSHOTTING  ################################
# 持久化,在规定时间内,执行操作会持久化到文件.rdb.aof
# 900s内至少有1个key进行修改,进行持久化操作
save 3600 1
# 300s内至少有100个key进行修改,进行持久化操作
save 300 100
# 60s内至少有10000个key进行修改,进行持久化操作
save 60 10000
# 持久化如果出错,是否进行持久化
stop-writes-on-bgsave-error yes
# 是否压缩rdb(持久化)文件
rdbcompression yes
# 是否错误校验rdb文件
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
# rdb文件保存目录
dir ./

安全

单位

1
2
3
4
5
6
7
8
################################## SECURITY ###################################

# ACL日志存储在内存中并消耗内存
acllog-max-len 128
# 设置密码 redis默认是没有密码的
requirepass 密码
# 将命令重命名
rename-command

限制

CLIENTS

1
2
3
4
5
6
7
################################### CLIENTS #################################### 
# 最大连接客户端数量
maxclients 10000
# redis配置最大内存容量
maxmemory <bytes>
# 内存到达上限后处理策略
maxmemory-policy noeviction

APPEND ONLY MODE

APPEND ONLY MODE

1
2
3
4
5
6
7
8
9
############################## APPEND ONLY MODE ###############################

# 默认不开启aof模式,默认使用rdb持久化
appendonly no
# 持久化文件名
appendfilename "appendonly.aof"
appenddirname "appendonlydir"
# 每次是否同步配置
appendfsync everysec