Redis中间件部署及使用

Redis中间件部署及使用

 

1. Redis的部署

1.1 CentOS7.x下的直接部署
  • 下载源码包
wget http://download.redis.io/releases/redis-4.0.10.tar.gz
  • 解压
tar -zxvf redis-4.0.10.tar.gz
  • 安装gcc环境
yum install -y gcc
  • 进入解压文件夹编译
cd redis-4.0.10
make MALLOC=libc
  • 安装redis服务到指定文件夹
make install PREFIX=/usr/local/redis
  • 启动redis服务
# 进入redis的bin目录
cd /usr/local/redis/bin

# 直接启动redis服务,使用redis的默认配置
./redis-server

# 通过redis的配置文件进行启动(配置文件在为解压文件夹中的redis.conf)
./redis-server ./redis.conf
  • 启动命令行客户端
# 进入redis的bin目录
cd /usr/local/redis/bin

# 启动命令行客户端
./redis-cli

1.2 CentOS7.x下通过Docker的安装部署
  • 安装部署命令
docker run -p 6379:6379 -v /usr/local/redis/conf/redis.conf:/etc/redis/redis.conf -v /usr/local/redis/data:/data --name redis-4.0.10 -d redis:4.0.10 redis-server /etc/redis/redis.conf
  • 命令说明
# 将容器的6379端口映射到主机的6379端口
-p 6379:6379

# 将主机/usr/local/redis/conf目录下redis.conf挂在到容器/etc/redis/redis.conf
-v /usr/local/redis/conf/redis.conf:/etc/redis/redis.conf

# 将主机 /usr/local/redis/data目录下的data挂载到容器的/data
-v /usr/local/redis/data:/data

  • 进入容器启动命令行客户端
# 进入容器
docker exec -it redis-4.0.10 /bin/bash

# 启动命令行客户端
redis-cli

1.3 Redis的配置文件常用配置
  • 配置后台运行
# 是否以后台进程运行,默认为no
daemonize yes
  • 配置端口
# 监听端口号,默认为6379
port 6379
  • 配置外网远程连接
# 绑定地址,默认为本地127.0.0.1
bind 0.0.0.0
  • 配置数据库数量
# 数据库数量,编号从0开始(默认使用0号库),默认为16
databases 16
  • 配置RDB(快照模式)持久化(默认持久化模式)
# 持久化文件名(必须以.rdb结尾),默认为dump.rdb
dbfilename dump.rdb

# 持久化文件存放的文件夹路径,默认为"./"
dir ./

# 持久化策略
save 900 1  # 在900s(15m)之后,至少有1个key发生变化,则快照
save 300 10  # 在300s(5m)之后,至少有10个key发生变化,则快照
save 60 10000 # 在60s(1m)之后,至少有1000个key发生变化,则快照

  • 配置AOF(日志追加模式)持久化
# 是否开启AOF持久化,默认为no
appendonly yes

# AOF持久化日志文件名(必须以.aof结尾),默认为appendonly.aof
appendfilename appendonly.aof

# 持久化文件存放的文件夹路径,默认为"./"
dir ./

# AOF持久化三种同步策略
appendfsync always  # 每次有数据发生变化时都会写入appendonly.aof
appendfsync everysec # 默认方式,每秒同步一次到appendonly.aof
appendfsync no    # 何时持久化交给操作系统决定进行

 


 

2. Redis的使用

2.1 命令行客户端操作指令
2.1.1 操作数据库的指令
  • 选择数据库
select 1	# 选择1号数据库
  • 清空数据库
# 清空当前数据库
flushdb

# 清空所有数据库
flushall

2.1.2 操作key的指令
  • 通过表达式查看key
keys *	# 查看所有key

# *表示通配0个或多个, 例如:a*可以匹配a、aa、ab、abb等
# ?表示通配1个,例如:a?可以匹配aa、ab、ac等
# []表示匹配一个[]内包含的任意一个,例如:[abc]可以匹配a、b、c
  • 查看key是否存在
exists name	# 是否存在key名为name的key

# 返回0表示不存在
# 返回1表示存在
  • 删除key
del name	# 删除key名为name的key
del name age # 删除key名为name和age的key(可一次删除多个key)
  • 设置key的过期时间
expire name 5	# 设置key名为name的key5秒后过期(删除)
pexpire name 5000	# 设置key名为name的key5000毫秒后过期(删除)

# 返回1表示设置成功
  • 查看key的过期时间
ttl name # 查看key名为name的key还有多少秒过期
pttl name # 查看key名为name的key还有多少毫秒过期

# 返回-2表示没有key
# 返回-1表示key永久存在(没有过期时间)
  • 将key移动到指定数据库
move name 1 # 将key名为name的key移入1号数据库
  • 获取一个随机key
randomkey
  • 更改key名
rename name name1	# 将key名为name的key改名为name1
  • 查看key对应值的类型
type name	# 查看key名为name的key对应值的类型

2.1.3 操作String类型的指令
  • 设置一个key/value
set name zhangsan	# 设置key为name,value为张三
  • 获取一个key对应的value
get name	# 获取key名为name的key对应的value
  • 设置多个key/value
mset name zhangsan age 18	# 设置key为name,value为张三;设置key为age,value为18
  • 设置一个key/value,同时设置key的过期时间
setex name 5 zhangsan	# 设置key为name,value为张三,过期时间为5秒
psetex name 5000 zhangsan	# 设置key为name,value为张三,过期时间为5000毫秒
  • 如果key不存在则设置一个key/value
setnx name zhangsan	# 如果key名为name的key不存在,则设置key为name,value为张三
  • 如果多个key同时不存在则设置多个key/value(只要有一个存在就全不设置)
msetnx name zhangsan age 18	# 如果key名为name和age的key不存在,则设置key为name,value为张三,设置key为age,value为18
  • 获取多个key对应的value
mget name age	# 获取key名为name的key对应的value;获取key名为age的key对应的value
  • 获取一个key的值并设置一个新值
getset name lisi	# 获取key名为name的key对应的value,并设置value为lisi
  • 获取key对应value的长度
strlen name	# 获取key名为name的key对应value的长度
  • 追加内容到key对应value的尾部
append name aaa	# 追加"aaa"到key名为name的key对应value的尾部
  • 获取key对应value的部分内容(下标从0开始)
getrange name 1 3	# 获取key名为name的key对应value下标从1到3的内容
getrange name 1 -1	# 获取key名为name的key对应value下标从1到末尾的内容
  • 若key对应value为数值类型,则value加1
incr age	# key名为age的key对应value加1
  • 若key对应value为数值类型,则value加自定义整数数值
incrby age 10 # key名为age的key对应value加10
  • 若key对应value为数值类型,则value减1
decr age	# key名为age的key对应value减1
  • 若key对应value为数值类型,则value减自定义整数数值
decrby age 10 # key名为age的key对应value减10
  • 若key对应value为数值类型,则value加自定义浮点数数值
incrbyfloat score 10.5 # key名为age的key对应value加10.5

2.1.4 操作List类型指令
  • 从列表首部添加一个或多个值到key列表中(key列表可以不存在)
lpush name zhangsan lisi wangwu	# 从列表首部添加zhangsan、lisi、wangwu到name列表中
  • 从列表首部添加一个或多个值到key列表中(key列表必须存在)
lpushx name zhangsan lisi wangwu	# 从列表首部添加zhangsan、lisi、wangwu到name列表中
  • 从列表尾部添加一个或多个值到key列表中(key列表可以不存在)
rpush name zhangsan lisi wangwu	# 从列表尾部添加zhangsan、lisi、wangwu到name列表中
  • 从列表尾部添加一个或多个值到key列表中(key列表必须存在)
rpushx name zhangsan lisi wangwu	# 从列表尾部添加zhangsan、lisi、wangwu到name列表中
  • 返回并移除列表首部的一个元素
lpop name	# 返回name列表首元素并移除
  • 返回并移除列表尾部的一个元素
rpop name	# 返回name列表尾元素并移除
  • 获取列表部分元素(下标从0开始)
lrange name 1 3	# 返回name列表下标为1到3的元素
lrange name 1 -1	# 返回name列表下标为1到末尾的元素
  • 获取列表的元素个数
llen name	# 获取name列表的元素个数
  • 设置列表对应下标元素的值(下标必须存在)
lset name 1 lisi	# 设置name列表下标为1的值为lisi
  • 获取列表指定下标的值
lindex name 1	# 获取name列表下标为1的值
  • 从头开始删除列表任意个数的相同值
lrem name 2 zhangsan	# 从头开始删除2个值为zhangsan的值
  • 保留列表下标区间的元素(下标从0开始)
ltrim name 1 3	# 保留name列表下标从1到3的元素
ltrim name 1 -1	# 保留name列表下标从1到末尾的元素
  • 在列表中插入一个元素
linsert name before lisi zhangsan	# 在name列表从头开始的第一个lisi前插入zhangsan
linsert name after lisi wangwu	# 在name列表从头开始的第一个lisi后插入wangwu

2.1.5 操作Set类型指令
  • 向集合中添加元素
sadd name zhangsan lisi wangwu	# 添加zhangsan、lisi、wangwu到name集合中
  • 获取集合中的所有元素
smembers name	# 获取name集合中的所有元素
  • 获取集合中元素的个数
scard name	# 获取name集合中元素的个数
  • 随机获取集合中的元素并移除
spop name	# 随机获取name集合中的一个元素并移除
spop name 2	# 随机获取name集合中的两个元素并移除
  • 将集合中的一个元素移动到另一个集合中
smove name1 name2 zhangsan	# 将name1集合中的zhangsan移动到name2集合中
  • 删除集合中的一个或多个元素
srem name zhangsan	# 删除name集合中的zhangsan
srem name zhangsan lisi	# 删除name集合中的zhangsan和lisi
  • 判断集合中是否存在某个元素
sismember name zhangsan	# 判断name集合中是否存在zhangsan
  • 随机返回集合中的元素
srandmember name	# 随机返回name集合中的一个元素
srandmember name 2	# 随机返回name集合中的两个元素
  • 获取一个集合相对于其他集合的补集元素
sdiff name1 name2 name3	# 获取name1集合相对于name2集合、name3集合的补集元素
  • 获取一个集合相对于其他集合的交集元素
sinter name1 name2 name3	# 获取name1集合相对于name2集合、name3集合的交集元素
  • 获取一个集合相对于其他集合的并集
sunion name1 name2 name3	# 获取name1集合相对于name2集合、name3集合的并集元素

2.1.6 操作ZSet类型的指令
  • 向有序集合中添加元素
zadd name 10 zhangsan 20 lisi 30 wangwu	# 添加zhangsan(10分)、lisi(20分)、wangwu(30分)到name有序集合中
  • 获取有序集合的元素个数
zcard name	# 获取name有序集合的元素个数
  • 获取有序集合部分元素(下标从0开始)
zrange name 1 3	# name有序集合按升序排列并返回下标为1到3的元素
zrange name 1 -1 withscores	# name有序集合按升序排列并返回下标为1到末尾的元素以及元素对应的分数

zrevrange name 1 3	# name有序集合按降序排列并返回下标为1到3的元素
zrevrange name 1 -1 withscores	# name有序集合按降序排列并返回下标为1到3的元素以及元素对应的分数

zrangebyscore name 0 100	# name有序集合按升序排列并返回元素分数为0到100的元素
zrangebyscore name 0 100 withscores	# name有序集合按升序排列并返回元素分数为0到100的元素以及元素对应的分数
zrangebyscore name 0 100 withscores limit 0 2	# name有序集合按升序排列并返回元素分数为0到100的前两个元素以及元素对应的分数
  • 获取有序集合某个元素的下标(下标从0开始)
zrank name zhangsan	# name有序集合按升序排列并返回zhangsan的下标

zrevrank name zhangsan	# name有序集合按降序排列并返回zhangsan的下标
  • 获取有序集合某个元素的的分数
zscore name zhangsan	# 获取name有序集合zhangsan的分数
  • 删除有序集合的一个或多个元素
zrem name zhangsan	# 删除name有序集合的zhangsan
zrem name zhangsan lisi	# 删除name有序集合的zhangsan和lisi
  • 为有序集合的某个元素增加自定义的分数
zincrby name 5 zhangsan	# 为name有序集合的zhangsan增加5分

2.1.7 操作Hash类型的指令
  • 设置一个key/value
hset person name zhangsan	# 设置key为person,value为一个key为name,value为zhangsan的键值对
  • 获取key对应value其中一个hashkey对应的值
hget person name	# 获取key名为person的key对应value其中一个hashkey为name对应的值
  • 同时设置多个key/value
hmset person name zhangsan age 18	# 设置key为person,value为一个key为name,value为zhangsan的键值对和一个key为age,value为18的键值对
  • 同时获取key对应value其中多个hashkey对应的值
hmget person name age	# 获取key名为person的key对应value中hashkey为name和age对应的值
  • 如果key对应value中hashkey不存在则设置一个key/value
hsetnx person name zhangsan	# 如果key名为person的key对应value中hashkey为name的hashkey不存在则设置一个hashkey为name,hashvalue为zhangsan的键值对
  • 获取key对应value中的所有键值对
hgetall person	# 获取key名为person的key对应value所有键值对
  • 删除key对应value中的一个或多个hashkey
hdel person name age	# 删除key名为person的key对应value中的name和age
  • 判断key对应value中的一个hashkey是否存在
hexists person name	# 判断key名为person的key对应value中的一个name是否存在
  • 获取key对应value中的所有hashkey
hkeys person	# 获取key名为person的key对应value中的所有hashkey
  • 获取key对应value中的所有hashvalue
hvals person	# 获取key名为person的key对应value中的所有hashvalue
  • 若key对应value中的hashkey对应hashvalue为数值类型,则hashvalue加自定义整数数值
hincrby person age 2	# key名为person的key对应value中的hashkey为age的hashkey对应的hashvalue加2
  • 若key对应value中的hashkey对应hashvalue为数值类型,则hashvalue加自定义浮点数数值
hincrbyfloat person score 1.5	# key名为person的key对应value中的hashkey为score的hashkey对应的hashvalue加1.5

2.2 原生Java操作Redis
  • 引入Redis依赖
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
  • 操作redis
import redis.clients.jedis.Jedis;

import java.util.Set;

/**
 * 测试Redis
 */
public class TestRedis {

    public static void main(String[] args) {

        // 创建Jedis客户端对象
        Jedis jedis = new Jedis("192.168.150.128", 6379);
        // 选择数据库(默认使用0号库)
        jedis.select(0);

        // Redis操作
        Set<String> keys = jedis.keys("*");
        keys.forEach(System.out::println);

        // 释放资源
        jedis.close();

    }

}

2.3 SpringBoot操作Redis
2.3.1 SpringBoot整合Redis
  • 新建SpringBoot项目
  • pom.xml依赖
<!--引入Redis依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • application.yml配置
# redis连接配置
spring:
  redis:
    host: 192.168.150.128
    port: 6379
    database: 0
  • 操作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.connection.DataType;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.*;
import java.util.concurrent.TimeUnit;

@SpringBootTest
class SpringbootRedisApplicationTests {

    /**
     * String类型Redis模板,key和value都为String类型
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 通用类型Redis模板,key和value都为Object类型
     */
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;


    @Test
    void stringRedisTemplateTest() {

        /* ************ 操作Key ************ */

        //  通过表达式查看key
        Set<String> keys = stringRedisTemplate.keys("*");
        keys.forEach(System.out::println);

        // 查看key是否存在
        Boolean hasKey = stringRedisTemplate.hasKey("name");
        System.out.println(hasKey);

        // 删除key
        Boolean delete = stringRedisTemplate.delete("name");
        System.out.println(delete);

        // 设置过期时间
        stringRedisTemplate.expire("name", 5, TimeUnit.SECONDS);

        // 查看过期时间
        Long expire = stringRedisTemplate.getExpire("name", TimeUnit.SECONDS);
        System.out.println(expire);

        // 移动key
        Boolean move = stringRedisTemplate.move("name", 1);
        System.out.println(move);

        // 随机获取一个key
        String randomKey = stringRedisTemplate.randomKey();
        System.out.println(randomKey);

        // 更改key名
        stringRedisTemplate.rename("name", "newname");

        // 查看key类型
        DataType type = stringRedisTemplate.type("name");
        System.out.println(type);


        /* ************ 操作String类型 ************ */

        Map<String, String> stringMap = new HashMap<>();
        stringMap.put("name", "zhangsan");
        stringMap.put("age", "18");

        // 添加一个key/value
        stringRedisTemplate.opsForValue().set("name", "zhangsan");

        // 获取一个key值
        String value = stringRedisTemplate.opsForValue().get("name");
        System.out.println(value);

        // 一次添加多个key/value
        stringRedisTemplate.opsForValue().multiSet(stringMap);

        // 添加一个key/value,同时设置过期时间
        stringRedisTemplate.opsForValue().set("name", "zhangsan", 5, TimeUnit.SECONDS);

        // 如果key不存在,添加一个key/value
        Boolean setIfAbsent = stringRedisTemplate.opsForValue().setIfAbsent("name", "zhangsan");
        System.out.println(setIfAbsent);

        // 如果多个key同时不存在则设置多个key/value(只要有一个存在就全不设置)
        stringRedisTemplate.opsForValue().multiSetIfAbsent(stringMap);

        // 同时获取多个key值
        List<String> multiGetValues = stringRedisTemplate.opsForValue().multiGet(Arrays.asList("name", "age"));
        multiGetValues.forEach(System.out::println);

        // 获取一个key的值并设置一个新值
        String oldValue = stringRedisTemplate.opsForValue().getAndSet("name", "lisi");
        System.out.println(oldValue);

        // 获取key对应value的长度
        Long size = stringRedisTemplate.opsForValue().size("name");
        System.out.println(size);

        // 追加内容到key对应value的尾部
        Integer append = stringRedisTemplate.opsForValue().append("name", "aaa");
        System.out.println(append);

        // 获取key对应value的部分内容(下标从0开始)
        String subName1 = stringRedisTemplate.opsForValue().get("name", 1, 3);// 获取key名为name的key对应value下标从1到3的内容
        String subName2 = stringRedisTemplate.opsForValue().get("name", 1, -1);// 获取key名为name的key对应value下标从1到末尾的内容
        System.out.println(subName1);
        System.out.println(subName2);

        // 若key对应value为数值类型,则value加1
        Long incrementOne = stringRedisTemplate.opsForValue().increment("age");
        System.out.println(incrementOne);

        // 若key对应value为数值类型,则value加自定义整数数值
        Long incrementAny = stringRedisTemplate.opsForValue().increment("age", 2);
        System.out.println(incrementAny);

        // 若key对应value为数值类型,则value减1
        Long decrementOne = stringRedisTemplate.opsForValue().decrement("age");
        System.out.println(decrementOne);

        // 若key对应value为数值类型,则value减自定义整数数值
        Long decrementAny = stringRedisTemplate.opsForValue().decrement("age", 2);
        System.out.println(decrementAny);

        // 若key对应value为数值类型,则value加自定义浮点数数值
        Double incrementDouble = stringRedisTemplate.opsForValue().increment("score", 1.5);
        System.out.println(incrementDouble);


        /* ************ 操作List类型 ************ */

        // 从列表首部添加一个值到key列表中
        Long leftPush = stringRedisTemplate.opsForList().leftPush("name", "zhangsan");
        System.out.println(leftPush);

        // 从列表首部添加多个值到key列表中
        Long leftPushAll = stringRedisTemplate.opsForList().leftPushAll("name", "zhangsan", "lisi");
        System.out.println(leftPushAll);

        // 从列表尾部添加一个值到key列表中
        Long rightPush = stringRedisTemplate.opsForList().rightPush("name", "zhangsan");
        System.out.println(rightPush);

        // 从列表尾部添加多个值到key列表中
        Long rightPushAll = stringRedisTemplate.opsForList().rightPush("name", "zhangsan", "lisi");
        System.out.println(rightPushAll);

        // 返回并移除列表首部的一个元素
        String leftPop = stringRedisTemplate.opsForList().leftPop("name");
        System.out.println(leftPop);

        // 返回并移除列表尾部的一个元素
        String rightPop = stringRedisTemplate.opsForList().rightPop("name");
        System.out.println(rightPop);

        // 获取列表部分元素(下标从0开始)
        List<String> range1 = stringRedisTemplate.opsForList().range("name", 0, 1);
        List<String> range2 = stringRedisTemplate.opsForList().range("name", 0, -1);
        range1.forEach(System.out::println);
        range2.forEach(System.out::println);

        // 获取列表的元素个数
        Long listSize = stringRedisTemplate.opsForList().size("name");
        System.out.println(listSize);

        // 设置列表对应下标元素的值(下标必须存在)
        stringRedisTemplate.opsForList().set("name", 0, "lisi");

        // 获取列表指定下标的值
        String index = stringRedisTemplate.opsForList().index("name", 0);
        System.out.println(index);

        // 从头开始删除列表任意个数的相同值
        Long remove = stringRedisTemplate.opsForList().remove("name", 2, "zhangsan");
        System.out.println(remove);

        // 保留列表下标区间的元素(下标从0开始)
        stringRedisTemplate.opsForList().trim("name", 1, 3);    // 留name列表下标从1到3的元素
        stringRedisTemplate.opsForList().trim("name", 1, -1);   // 保留name列表下标从1到末尾的元素

        // 在列表中某元素前插入一个元素
        Long leftInsert = stringRedisTemplate.opsForList().leftPush("name", "lisi", "zhangsan");    // 在name列表从头开始的第一个lisi前插入zhangsan
        System.out.println(leftInsert);

        // 在列表中某元素后插入一个元素
        Long rightInsert = stringRedisTemplate.opsForList().rightPush("name", "lisi", "wangwu");    // 在name列表从头开始的第一个lisi后插入wangwu
        System.out.println(rightInsert);


        /* ************ 操作Set类型 ************ */

        // 向集合中添加一个或多个元素
        Long add = stringRedisTemplate.opsForSet().add("name", "zhangsan", "lisi");
        System.out.println(add);

        // 获取集合中的所有元素
        Set<String> members = stringRedisTemplate.opsForSet().members("name");
        members.forEach(System.out::println);

        // 获取集合中元素的个数
        Long sSize = stringRedisTemplate.opsForSet().size("name");
        System.out.println(sSize);

        // 随机获取集合中的元素并移除
        String sPopOne = stringRedisTemplate.opsForSet().pop("name");   // 随机获取name集合中的一个元素并移除
        List<String> sPopAny = stringRedisTemplate.opsForSet().pop("name", 2);  // 随机获取name集合中的两个元素并移除
        System.out.println(sPopOne);
        sPopAny.forEach(System.out::println);

        // 将集合中的一个元素移动到另一个集合中
        Boolean sMove = stringRedisTemplate.opsForSet().move("name1", "zhangsan", "name2"); // 将name1集合中的zhangsan移动到name2集合中
        System.out.println(sMove);

        // 删除集合中的一个或多个元素
        stringRedisTemplate.opsForSet().remove("name", "zhangsan", "lisi");

        // 判断集合中是否存在某个元素
        Boolean isMember = stringRedisTemplate.opsForSet().isMember("name", "zhangsan");
        System.out.println(isMember);

        // 随机返回集合中的一个元素
        String randomMember = stringRedisTemplate.opsForSet().randomMember("name");
        System.out.println(randomMember);

        // 随机返回集合中的多个元素
        List<String> randomMembers = stringRedisTemplate.opsForSet().randomMembers("name", 2);
        randomMembers.forEach(System.out::println);

        // 获取一个集合相对于其他集合的补集元素
        Set<String> difference = stringRedisTemplate.opsForSet().difference("name1", Arrays.asList("name2", "name3"));
        difference.forEach(System.out::println);

        // 获取一个集合相对于其他集合的交集元素
        Set<String> intersect = stringRedisTemplate.opsForSet().intersect("name1", Arrays.asList("name2", "name3"));
        intersect.forEach(System.out::println);

        // 获取一个集合相对于其他集合的并集
        Set<String> union = stringRedisTemplate.opsForSet().union("name1", Arrays.asList("name2", "name3"));
        union.forEach(System.out::println);


        /* ************ 操作ZSet类型 ************ */

        Set<ZSetOperations.TypedTuple<String>> zSet = new HashSet<>();
        zSet.add(new DefaultTypedTuple<>("zhagnsan", 10.0));
        zSet.add(new DefaultTypedTuple<>("lisi", 20.0));

        // 向有序集合中添加一个元素
        Boolean zAddOne = stringRedisTemplate.opsForZSet().add("name", "zhangsan", 10);// 添加zhangsan(10分)到name有序集合中
        System.out.println(zAddOne);

        // 向有序集合中添加多个元素
        Long zAddAny = stringRedisTemplate.opsForZSet().add("name", zSet);
        System.out.println(zAddAny);

        // 获取有序集合的元素个数
        Long zSize = stringRedisTemplate.opsForZSet().size("name");
        System.out.println(zSize);

        // 获取有序集合部分元素(下标从0开始)
        Set<String> zRange1 = stringRedisTemplate.opsForZSet().range("name", 1, 3); // name有序集合按升序排列并返回下标为1到3的元素
        zRange1.forEach(System.out::println);

        Set<ZSetOperations.TypedTuple<String>> zRang2 = stringRedisTemplate.opsForZSet().rangeWithScores("name", 1, -1);    // name有序集合按升序排列并返回下标为1到末尾的元素以及元素对应的分数
        zRang2.forEach(typedTuple -> {
            System.out.println(typedTuple.getValue());
            System.out.println(typedTuple.getScore());
        });

        Set<String> zRevRange1 = stringRedisTemplate.opsForZSet().reverseRange("name", 1, 3);   // name有序集合按降序排列并返回下标为1到3的元素
        zRevRange1.forEach(System.out::println);

        Set<ZSetOperations.TypedTuple<String>> zRevRange2 = stringRedisTemplate.opsForZSet().reverseRangeWithScores("name", 1, -1);    // name有序集合按升序排列并返回下标为1到末尾的元素以及元素对应的分数
        zRevRange2.forEach(typedTuple -> {
            System.out.println(typedTuple.getValue());
            System.out.println(typedTuple.getScore());
        });

        Set<String> rangeByScore = stringRedisTemplate.opsForZSet().rangeByScore("name", 0, 100);   // name有序集合按升序排列并返回元素分数为0到100的元素
        rangeByScore.forEach(System.out::println);

        Set<ZSetOperations.TypedTuple<String>> rangeByScoreWithScores1 = stringRedisTemplate.opsForZSet().rangeByScoreWithScores("name", 0, 100);   // name有序集合按升序排列并返回元素分数为0到100的元素以及元素对应的分数
        rangeByScoreWithScores1.forEach(typedTuple -> {
            System.out.println(typedTuple.getValue());
            System.out.println(typedTuple.getScore());
        });

        Set<ZSetOperations.TypedTuple<String>> rangeByScoreWithScores2 = stringRedisTemplate.opsForZSet().rangeByScoreWithScores("name", 0, 100, 0, 2);   // name有序集合按升序排列并返回元素分数为0到100的前两个元素以及元素对应的分数
        rangeByScoreWithScores2.forEach(typedTuple -> {
            System.out.println(typedTuple.getValue());
            System.out.println(typedTuple.getScore());
        });

        // 获取有序集合某个元素的下标(下标从0开始)
        Long rank = stringRedisTemplate.opsForZSet().rank("name", "zhangsan");  // name有序集合按升序排列并返回zhangsan的下标
        System.out.println(rank);

        Long reverseRank = stringRedisTemplate.opsForZSet().reverseRank("name", "zhangsan");    // name有序集合按降序排列并返回zhangsan的下标
        System.out.println(reverseRank);

        // 获取有序集合某个元素的的分数
        Double score = stringRedisTemplate.opsForZSet().score("name", "zhangsan");
        System.out.println(score);

        // 删除有序集合的一个或多个元素
        Long zRemove = stringRedisTemplate.opsForZSet().remove("name", "zhangsan", "lisi");
        System.out.println(zRemove);

        // 为有序集合的某个元素增加自定义的分数
        Double incrementScore = stringRedisTemplate.opsForZSet().incrementScore("name", "zhangsan", 5);
        System.out.println(incrementScore);


        /* ************ 操作Hash类型 ************ */

        Map<String, Object> hash = new HashMap<>();
        hash.put("name", "zhangsan");
        hash.put("age", 18);

        // 设置一个key/value
        stringRedisTemplate.opsForHash().put("person", "name", "zhangsan");

        // 获取key对应value其中一个hashkey对应的值
        Object hashValue = stringRedisTemplate.opsForHash().get("person", "name");
        System.out.println(hashValue);

        // 同时设置多个key/value
        stringRedisTemplate.opsForHash().putAll("person", hash);

        // 同时获取key对应value其中多个hashkey对应的值
        List<Object> multiGet = stringRedisTemplate.opsForHash().multiGet("person", Arrays.asList("name", "age"));
        multiGet.forEach(System.out::println);

        // 如果key对应value中hashkey不存在则设置一个key/value
        Boolean putIfAbsent = stringRedisTemplate.opsForHash().putIfAbsent("person", "name", "zhangsan");
        System.out.println(putIfAbsent);

        // 获取key对应value中的所有键值对
        Map<Object, Object> person = stringRedisTemplate.opsForHash().entries("person");
        System.out.println(person);

        // 删除key对应value中的一个或多个hashkey
        Long hashDelete = stringRedisTemplate.opsForHash().delete("person", "name", "age");
        System.out.println(hashDelete);

        // 判断key对应value中的一个hashkey是否存在
        Boolean hashHasKey = stringRedisTemplate.opsForHash().hasKey("person", "name");
        System.out.println(hashHasKey);

        // 获取key对应value中的所有hashkey
        Set<Object> hashKeys = stringRedisTemplate.opsForHash().keys("person");
        hashKeys.forEach(System.out::println);

        // 获取key对应value中的所有hashvalue
        List<Object> hashValues = stringRedisTemplate.opsForHash().values("person");
        hashValues.forEach(System.out::println);

        // 若key对应value中的hashkey对应hashvalue为数值类型,则hashvalue加自定义整数数值
        Long hashIncrement1 = stringRedisTemplate.opsForHash().increment("person", "age", 2);
        System.out.println(hashIncrement1);

        // 若key对应value中的hashkey对应hashvalue为数值类型,则hashvalue加自定义浮点数数值
        Double hashIncrement2 = stringRedisTemplate.opsForHash().increment("person", "score", 1.5);
        System.out.println(hashIncrement2);

    }

    @Test
    void redisTemplateTest() {

        // 设置key以String方式序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // 设置hashKey以String方式序列化
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        // 以绑定的方式操作key(用于简化书写多次操作同一个key)
        BoundValueOperations<Object, Object> boundValueOps = redisTemplate.boundValueOps("name");
        boundValueOps.set("zhangsan");
        boundValueOps.append("aaa");

        /* ************ 操作redis同stringRedisTemplate ************ */

    }

}

2.3.2 通过Mybatis的二级缓存实现分布式缓存
  • pom.xml依赖
<dependencies>

    <!--web依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--redis依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <!--mysql数据库驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>

    <!--mybatis依赖-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.3</version>
    </dependency>

    <!--druid数据源-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.20</version>
    </dependency>

    <!--lombok依赖-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <!--测试依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>

</dependencies>
  • application.yml配置
# web端口
server:
  port: 8080

spring:

  application:
    name: rediscache

  # redis连接配置
  redis:
    host: 192.168.150.128
    port: 6379
    database: 0

  # mysql连接配置
  datasource:
    # 数据库连接
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password:

    # 数据源配置
    type: com.alibaba.druid.pool.DruidDataSource

# mybatis配置
mybatis:
  mapper-locations: classpath*:mapper/**/*.xml
  type-aliases-package: com.mo.rediscache.model.entity

# 日志配置
logging:
  level:
    com.mo.rediscache.mapper: debug
  • Spring容器工具类
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * Spring容器工具类
 */
@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    /** Spring容器 */
    private static ApplicationContext applicationContext;

    /**
     * Spring容器设置
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtils.applicationContext = applicationContext;
    }

    /**
     * 获取Bean
     */
    public static Object getBean(String beanName) {
        return ApplicationContextUtils.applicationContext.getBean(beanName);
    }

}
  • 自定义Redis缓存类
import com.mo.rediscache.util.ApplicationContextUtils;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.DigestUtils;

/**
 * Redis缓存
 */
public class RedisCache implements Cache {

    /** 缓存命名空间唯一标识 */
    private final String id;


    /**
     * Redis缓存构造方法
     *
     * @param id 缓存命名空间唯一标识
     */
    public RedisCache(String id) {
        this.id = id;
    }

    /**
     * 返回缓存命名空间唯一标识
     */
    @Override
    public String getId() {
        return this.id;
    }

    /**
     * 添加缓存
     */
    @Override
    public void putObject(Object key, Object value) {
        this.getRedisTemplate().opsForHash().put(this.id, this.md5Key(key), value);
    }

    /**
     * 获取缓存
     */
    @Override
    public Object getObject(Object key) {
        return this.getRedisTemplate().opsForHash().get(this.id, this.md5Key(key));
    }

    /**
     * 删除缓存(保留方法)
     */
    @Override
    public Object removeObject(Object key) {
        return null;
    }

    /**
     * 清空缓存
     */
    @Override
    public void clear() {
        this.getRedisTemplate().delete(this.id);
    }

    /**
     * 获取缓存数量
     */
    @Override
    public int getSize() {
        return this.getRedisTemplate().opsForHash().size(this.id).intValue();
    }

    /**
     * 获取Redis操作模板对象
     */
    private RedisTemplate<String, Object> getRedisTemplate() {

        // 获取Redis操作模板对象
        RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) ApplicationContextUtils.getBean("redisTemplate");
        // 设置key以String方式序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // 设置hashKey以String方式序列化
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        return redisTemplate;
    }

    /**
     * 获取key的MD5值
     */
    private String md5Key(Object key) {
        return DigestUtils.md5DigestAsHex(key.toString().getBytes());
    }

}
  • Person实体类
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

@Data
@Accessors(chain = true)
public class Person implements Serializable {

    private Integer id;
    private String name;
    private Integer age;
    private Boolean sex;

    private Telephone telephone;

}
  • Telephone实体类
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

@Data
@Accessors(chain = true)
public class Telephone implements Serializable {

    private Integer id;
    private String number;

}
  • PersonMapper接口
import com.mo.rediscache.model.entity.Person;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface PersonMapper {

    // 获取所有数据
    List<Person> findAll();

}
  • TelephoneMapper接口
import com.mo.rediscache.model.entity.Telephone;
import org.springframework.stereotype.Repository;

@Repository
public interface TelephoneMapper {

    // 通过ID查询数据
    Telephone getTelephoneById(Integer id);

}
  • PersonMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mo.rediscache.mapper.PersonMapper">

    <!--开启二级缓存-->
    <cache type="com.mo.rediscache.cache.RedisCache" />

    <resultMap id="personMap" type="Person">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <result property="sex" column="sex"/>
        <association property="telephone" select="com.mo.rediscache.mapper.TelephoneMapper.getTelephoneById" column="telephone_id"></association>
    </resultMap>

    <select id="findAll" resultMap="personMap">
        SELECT id, name, age, sex, telephone_id
        FROM person
    </select>

</mapper>
  • TelephoneMappe.xml映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mo.rediscache.mapper.TelephoneMapper">

    <!--开启二级缓存关联-->
    <cache-ref namespace="com.mo.rediscache.mapper.PersonMapper"/>

    <select id="getTelephoneById" parameterType="Integer" resultType="Telephone">
        SELECT id, number
        FROM telephone
        WHERE id = #{id}
    </select>

</mapper>
  • PersonService接口
import com.mo.rediscache.model.entity.Person;

import java.util.List;

public interface PersonService {

    List<Person> findAll();

}
  • TelephoneService接口
import com.mo.rediscache.model.entity.Telephone;

public interface TelephoneService {

    // 通过ID查询数据
    Telephone getTelephoneById(Integer id);

}
  • PersonServiceImpl实现类
import com.mo.rediscache.mapper.PersonMapper;
import com.mo.rediscache.model.entity.Person;
import com.mo.rediscache.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonMapper personMapper;

    @Override
    public List<Person> findAll() {
        return personMapper.findAll();
    }

}
  • TelephoneServiceImpl实现类
import com.mo.rediscache.mapper.TelephoneMapper;
import com.mo.rediscache.model.entity.Telephone;
import com.mo.rediscache.service.TelephoneService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TelephoneServiceImpl implements TelephoneService {

    @Autowired
    private TelephoneMapper telephoneMapper;

    @Override
    public Telephone getTelephoneById(Integer id) {
        return telephoneMapper.getTelephoneById(id);
    }
}
  • application启动类
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.mo.rediscache.mapper")
@SpringBootApplication
public class RediscacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(RediscacheApplication.class, args);
    }

}
  • 测试类
import com.mo.rediscache.model.entity.Person;
import com.mo.rediscache.service.PersonService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@SpringBootTest(classes = RediscacheApplication.class)
@RunWith(SpringRunner.class)
public class RediscacheApplicationTests {

    @Autowired
    private PersonService personService;


    @Test
    public void test() {

        System.out.println("第一次获取值:");
        List<Person> personList = personService.findAll();
        personList.forEach(System.out::println);
        System.out.println("================================");
        System.out.println("第二次获取值:");
        List<Person> personList2 = personService.findAll();
        personList2.forEach(System.out::println);

    }

}

2.3.3 通过接管spring提供的session实现分布式session管理
  • pom.xml依赖
<dependencies>

    <!--web依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--redis操作依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <!--redis管理session依赖-->
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>

    <!--测试依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>

</dependencies>
  • application.yml配置
# web端口
server:
  port: 8080

spring:

  application:
    name: redissession

  # redis连接配置
  redis:
    host: 192.168.150.128
    port: 6379
    database: 0
  • Redis管理Session配置类
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
 * Redis管理Session配置类
 */
@Configuration
@EnableRedisHttpSession // 开启RedisHttpSession
public class RedisSessionManagerConfiguration {
}
  • controller测试
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@Controller
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/look")
    public void look(HttpServletRequest request, HttpServletResponse response) throws IOException {

        // 获取Session
        HttpSession session = request.getSession();

        // 获取Session中的数据
        Integer look = (Integer) session.getAttribute("look");

        if (look == null) {
            look = 0;
        }

        look += 1;

        // 同步Redis中的Session数据
        session.setAttribute("look", look);

        response.getWriter().println("look: " + look);
        response.getWriter().println("sessionid: " + session.getId());
    }

}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值