目录
3.2.安装ruby脚本运行所需的依赖包gem(redis版本<5.xxx)
4.2.配置文件application.properties
1.Redis安装
1.1.下载并解压Redis linux版本
在redis官网下载最新的版本,我这里是6.0.6版本,http://download.redis.io/releases/redis-6.0.6.tar.gz,一般上传到/opt目录下
解压redis-6.0.6.tar.gz:
tar -zxvf redis-6.0.6.tar.gz
1.2.安装C++ 环境
#安装gcc套装(如果是新系统gcc通常安装不全面)
yum install -y cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make
#升级gcc
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
#设置永久升级(选做)
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
1.3.安装redis
1.进入目录/opt/redis/redis-6.0.6/下,执行
make
#默认安装到了/usr/local/bin下,也可以通过PREFIX来指定安装目录
make install或者make install PREFIX=/usr/local/redis
redis的默认安装路径在/usr/local/bin下
2.拷贝redis.conf到/usr/local/bin下
cd /usr/local/bin
mkdir config
cp /opt/redis/redis-6.0.6/redis.conf config/
3.修改配置文件redis.conf中的daemonize yes,启动挂到后台
启动redis命令:
redis-server config/redis.conf
连接redis命令
#查看redis服务是否开启
ps -ef|grep redis
#连接redis服务
redis-cli -p 6379
#退出redis-cli
exit
#关闭redis-server
shutdown
1.4.设置开机自启动
1. 拷贝redis源码包中的启动脚本到/etc/init.d下,可以顺便起个名字叫redis
cp /opt/redis/redis-6.0.6/utils/redis_init_script /etc/init.d/redis
2.有兴趣可以读一下这个启动脚本,关键的地方检查一下,一个是服务端路径(EXEC和CLIEXEC),一个是CONF的配置文件路径,叫6379.conf
所以需要接着拷贝配置文件
#创建文件夹redis
cd /etc
mkdir redis
#从源码出拷贝配置文件,并修改文件名称成6379.conf
cp /opt/redis/redis-6.0.6/redis.conf /etc/redis/6379.conf
这里也可以修改6379.conf文件的内容,比如注释掉bind 127.0.0.1,protected-mode no等等
3.开机自启动设置
#添加redis服务
chkconfig --add redis
#设为开机启动
chkconfig redis on
#常用命令
service redis start
service redis stop
如果提示service redis does not support chkconfig,做如下操作
使用vim编辑redis-toutou文件,在第一行加入如下两行注释,保存退出
# chkconfig: 2345 90 10
# description: Redis is a persistent key-value database
注释的意思是,redis服务必须在运行级2,3,4,5下被启动或关闭,启动的优先级是90,关闭的优先级是10。
再次执行开机自启命令。
chkconfig redis on
2.Redis多哨兵模式
概述
Redis-Sentinel是官方推荐的高可用解决方案,当redis在做master-slave的高可用方案时,假如master宕机了,redis本身(以及其很多客户端)都没有实现自动进行主备切换,而redis-sentinel本身也是独立运行的进程,可以部署在其他与redis集群可通讯的机器中监控redis集群。
工作机制
Redis提供了sentinel(哨兵)机制,通过sentinel模式启动redis后,自动监控master/slave的运行状态,基本原理是:心跳机制+投票裁决 。每个sentinel会向其它sentinal、master、slave定时发送消息,以确认对方是否“活”着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的“主观认为宕机” Subjective Down,简称SDOWN)。
若”哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master”彻底死亡”(即:客观上的真正down机,Objective Down,简称ODOWN),通过一定的vote算法,从剩下的slave节点中,选一台提升为master,然后自动修改相关配置
哨兵模式是建立在主从复制+读写分离集群的基础上的,多了一个独立的哨兵进程,用于监控主节点和从节点的Redis
#切换到工作目录下
cd cd /usr/local/bin/
mkdir redis-sentinel
#从源码复制3个redis.conf配置文件以及3个哨兵配置文件sentinel.conf,并用不同的端口号命名
#其中6379是master,6380和6381是slave
cp /opt/redis/redis-6.0.6/redis.conf /usr/local/bin/redis-sentinel/redis6379.conf
cp /opt/redis/redis-6.0.6/redis.conf /usr/local/bin/redis-sentinel/redis6380.conf
cp /opt/redis/redis-6.0.6/redis.conf /usr/local/bin/redis-sentinel/redis6381.conf
cp /opt/redis/redis-6.0.6/sentinel.conf /usr/local/bin/redis-sentinel/sentinel26379.conf
cp /opt/redis/redis-6.0.6/sentinel.conf /usr/local/bin/redis-sentinel/sentinel26380.conf
cp /opt/redis/redis-6.0.6/sentinel.conf /usr/local/bin/redis-sentinel/sentinel26381.conf
依次修改新拷贝的3个redis.conf文件内容,注意端口
daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
# bind 127.0.0.1 可选,默认就处理所有请求。
logfile "./redis-6379.log"
dir "/usr/local/bin/redis-sentinel/"
#redis配置密码的话,需要以下配置
#masterauth "123456"
#requirepass "123456"
依次修改新拷贝的3个sentinel.conf文件内容,注意端口
daemonize yes
port 26379
#指定工作目录
dir "/usr/local/bin/redis-sentinel"
logfile "./sentinel26379.log"
#指定别名 主节点地址 端口 哨兵个数(有几个哨兵监控到主节点宕机执行转移)
sentinel monitor mymaster 127.0.0.1 6379 2
#如果哨兵3s内没有收到主节点的心跳,哨兵就认为主节点宕机了,默认是30秒
sentinel down-after-milliseconds mymaster 3000
#选举出新的主节点之后,可以同时连接从节点的个数
sentinel parallel-syncs mymaster 1
#如果10秒后,master仍没活过来,则启动failover,默认180s
sentinel failover-timeout mymaster 10000
#配置连接redis主节点密码,有就配置,没有就忽略
#sentinel auth-pass mymaster 123456
分别启动3个redis实例,改变主从关系,启动3个sentinel实例
#切换到工作路径,启动3个redis实例
cd /usr/local/bin
redis-server /usr/local/bin/redis-sentinel/redis6379.conf
redis-server /usr/local/bin/redis-sentinel/redis6380.conf
redis-server /usr/local/bin/redis-sentinel/redis6381.conf
#动态改变主从关系,成为6379的slave
redis-cli -p 6380
slaveof 127.0.0.1 6379
#检查一下是否是slave
info replication
exit
redis-cli -p 6380
slaveof 127.0.0.1 6379
#检查一下是否是slave
info replication
exit
redis-cli -p 6381
slaveof 127.0.0.1 6379
#检查一下是否是slave
info replication
exit
#查看主从关系
redis-cli -p 6379
#检查一下是否是master,2个slave
info replication
exit
#启动3个sentinel实例
redis-sentinel /usr/local/bin/redis-sentinel/sentinel26379.conf
redis-sentinel /usr/local/bin/redis-sentinel/sentinel26380.conf
redis-sentinel /usr/local/bin/redis-sentinel/sentinel26381.conf
3.Redis Cluster集群
Redis哨兵模式不能动态扩充,到Redis3.x之后,提出了cluster集群模式。
Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
结构特点
结构特点:
1、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
2、节点的fail是通过集群中超过半数的节点检测失效时才生效。
3、客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
4、redis-cluster把所有的物理节点映射到[0-16383]哈希槽上(不一定是平均分配),cluster 负责维护node<->哈希槽<->value。
5、Redis集群预分好16384个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个哈希槽中例如3个节点的Redis:
节点A覆盖0-5460;
节点B覆盖5461-10922;
节点C覆盖10923-16383.
由于redis-cluster采用投票容错的方式来判断该节点是否挂掉,投票容错简单点说就是投票超总数的一半即判定该节点挂掉,因此最少需要三个节点,但是由于redis-cluster要保证高可用,因此每个主节点需要一个备份机,也就是说至少需要六个节点
redis版本>=5.xxx,直接使用 ./redis-cli --cluster create 指令构建redis集群。
redis版本<5.xxx,需要安装ruby、rubygems环境,使用 ./redis-trib.rb create 指令构建redis集群,
请注意你的redis版本,redis版本>=5.xxx,不需要执行3.1和3.2操作
3.1.安装Ruby环境(redis版本<5.xxx)
# 安装基本工具
yum -y install ruby ruby-devel rubygems rpm-build
# 查看ruby版本,一般都是版本太低,至少需要2.3以上
ruby -v
#ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
# 安装yum源
yum install -y centos-release-scl-rh
# 安装指定版本的ruby
yum install -y rh-ruby24
#使升级后的配置生效
scl enable rh-ruby24 bash
# 查看ruby版本
ruby -v
#ruby 2.4.6p354 (2019-04-01 revision 67394) [x86_64-linux]
# 这里有个坑,一旦重启reboot now后,版本又变回去了,解决如下:
vim /etc/profile.d/rh-ruby24.sh
#内容如下:
#!/bin/bash
source /opt/rh/rh-ruby24/enable
export X_SCLS="`scl enable rh-ruby24 'echo $X_SCLS'`"
export PATH=$PATH:/opt/rh/rh-ruby24/root/usr/local/bin
# 使升级后的配置生效,加载环境变量
scl enable rh-ruby24 bash
# 查看ruby版本
ruby -v
#ruby 2.4.6p354 (2019-04-01 revision 67394) [x86_64-linux]
3.2.安装ruby脚本运行所需的依赖包gem(redis版本<5.xxx)
下载网站:https://bundler.rubygems.org/gems/redis/versions/4.2.5
#将下载后的redis-4.2.5.gem上传到/usr/local/bin/cluster-config下
redis-4.2.5.gem
#安装依赖包
gem install redis-4.2.5.gem
#将redis源码包下的redis-trib.rb复制到redis-cluster目录下
cp /opt/redis/redis-6.0.6/src/redis-trib.rb /usr/local/bin/cluster-config/
3.3.设置6个实例配置文件并脚本启动
cd /usr/local/bin/cluster-config
mkdir 6379 6380 6381 6382 6383 6384
cp /opt/redis/redis-6.0.6/redis.conf/redis.conf 6379/redis.conf
cp /opt/redis/redis-6.0.6/redis.conf/redis.conf 6380/redis.conf
cp /opt/redis/redis-6.0.6/redis.conf/redis.conf 6381/redis.conf
cp /opt/redis/redis-6.0.6/redis.conf/redis.conf 6382/redis.conf
cp /opt/redis/redis-6.0.6/redis.conf/redis.conf 6383/redis.conf
cp /opt/redis/redis-6.0.6/redis.conf/redis.conf 6384/redis.conf
#拷贝redis-server到6379 6380 6381 6382 6383 6384文件夹之中
cp ../redis-server 6379
cp ../redis-server 6380
cp ../redis-server 6381
cp ../redis-server 6382
cp ../redis-server 6383
cp ../redis-server 6384
每一个redis.conf都修改如下内容(最低修改):
port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
编写脚本,启动6个redis实例
cd /usr/local/bin/cluster-config
vim start.sh
#内容如下:
cd 6379
./redis-server redis.conf
cd ..
cd 6380
./redis-server redis.conf
cd ..
cd 6381
./redis-server redis.conf
cd ..
cd 6382
./redis-server redis.conf
cd ..
cd 6383
./redis-server redis.conf
cd ..
cd 6384
./redis-server redis.conf
cd ..
#设置执行权限
chmod ugo+x start.sh
#运行start.sh脚本
./start.sh
如下图所示
3.4.创建集群
至此6个redis节点启动成功,接下来正式开启搭建集群,以上都是准备条件
(redis版本<5.xxx)
./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
(redis版本>=5.xxx)
redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1
使用create命令 --replicas 1 参数表示为每个主节点创建一个从节点,其他参数是实例的地址集合。
[root cluster-config]# redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:6383 to 127.0.0.1:6379
Adding replica 127.0.0.1:6384 to 127.0.0.1:6380
Adding replica 127.0.0.1:6382 to 127.0.0.1:6381
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 6c731751599000bfb2af12ff62354fe82d1d7b84 127.0.0.1:6379
slots:[0-5460] (5461 slots) master
M: eee9755723c541ff5d88945febe5a4fd2b2a1001 127.0.0.1:6380
slots:[5461-10922] (5462 slots) master
M: 4c23d8f1139c04bdd341b34ac84d880827550241 127.0.0.1:6381
slots:[10923-16383] (5461 slots) master
S: 7e87d571592088aa7dcd06182e00ce21b3468e32 127.0.0.1:6382
replicates eee9755723c541ff5d88945febe5a4fd2b2a1001
S: e38fb18fc4c493f23ce7c9743857f905e84081f7 127.0.0.1:6383
replicates 4c23d8f1139c04bdd341b34ac84d880827550241
S: 08a1d2f9868c6dda312e60c23299667d716acc1e 127.0.0.1:6384
replicates 6c731751599000bfb2af12ff62354fe82d1d7b84
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: 6c731751599000bfb2af12ff62354fe82d1d7b84 127.0.0.1:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 4c23d8f1139c04bdd341b34ac84d880827550241 127.0.0.1:6381
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 7e87d571592088aa7dcd06182e00ce21b3468e32 127.0.0.1:6382
slots: (0 slots) slave
replicates eee9755723c541ff5d88945febe5a4fd2b2a1001
S: e38fb18fc4c493f23ce7c9743857f905e84081f7 127.0.0.1:6383
slots: (0 slots) slave
replicates 4c23d8f1139c04bdd341b34ac84d880827550241
S: 08a1d2f9868c6dda312e60c23299667d716acc1e 127.0.0.1:6384
slots: (0 slots) slave
replicates 6c731751599000bfb2af12ff62354fe82d1d7b84
M: eee9755723c541ff5d88945febe5a4fd2b2a1001 127.0.0.1:6380
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
两条redis集群基本命令
# 查看当前集群信息
cluster info
# 查看集群里有多少个节点
cluster nodes
3.5.集群扩容
新建6385、6386节点,加入集群,指定6385为主,6386为从,并为6385分配384个槽位
1.准备工作
# 切换目录
cd /usr/local/bin/cluster-config
mkdir 6385 6386
# 分别生成配置文件,并修改端口号
cp 6379/redis.conf 6385/
cp 6379/redis.conf 6386/
cp ../redis-server 6385/
cp ../redis-server 6386/
# 启动服务
6385/redis-server 6385/redis.conf
6386/redis-server 6386/redis.conf
查看redis cluster集群的命名大全
# 切换目录
cd /usr/local/bin/cluster-config
redis-cli --cluster help
2.将新节点中的master节点6385加入已有集群
# 切换目录
cd /usr/local/bin/cluster-config
redis-cli -h 127.0.0.1 -p 6379 --cluster add-node 127.0.0.1:6385 127.0.0.1:6379
# 查询集群
redis-cli -h 127.0.0.1 -p 6379 cluster nodes
3.将新节点中的slave节点6386加入集群(–cluster-slave),指定master节点集群Id(–cluster-master-id)
# 切换目录
cd /usr/local/bin/cluster-config
redis-cli -h 127.0.0.1 -p 6379 --cluster add-node 127.0.0.1:6386 127.0.0.1:6379 --cluster-slave --cluster-master-id a4e969f80ca9634e83cc0cc6e8ea1a4689dcba5b
# 其中a4e969f80ca9634e83cc0cc6e8ea1a4689dcba5b指的是6385的id
4.给新master节点(6385)分配槽位
redis-cli -h 127.0.0.1 -p 6379 --cluster reshard 127.0.0.1:6385
分配多少槽位
How many slots do you want to move (from 1 to 16384)? 384
分配给哪个节点(6385节点集群Id)
What is the receiving node ID? a4e969f80ca9634e83cc0cc6e8ea1a4689dcba5b
从哪个节点分割槽位给新节点,可以多个,输入done表示结束(6379节点集群Id:63249b39e5fade6fa6f17b6158ccbc1f9f0996ea)
Source node #1: 63249b39e5fade6fa6f17b6158ccbc1f9f0996ea
Source node #2: done
接着输入yes确认分配,查看集群信息,分配完成
Do you want to proceed with the proposed reshard plan (yes/no)? yes
3.6.集群缩容
1.归还6379节点槽位
# 切换目录
cd /usr/local/bin/cluster-config
redis-cli -h 127.0.0.1 -p 6379 --cluster reshard --cluster-from a4e969f80ca9634e83cc0cc6e8ea1a4689dcba5b --cluster-to 63249b39e5fade6fa6f17b6158ccbc1f9f0996ea --cluster-slots 384 127.0.0.1:6385
输入yes确认
Do you want to proceed with the proposed reshard plan (yes/no)? yes
2.移除6385、6386节点
# 切换目录
cd /usr/local/bin/cluster-config
redis-cli --cluster del-node 127.0.0.1:6385 1de56b252c703cd8fec6356d30088f188a3537b7
redis-cli --cluster del-node 127.0.0.1:6386 a4e969f80ca9634e83cc0cc6e8ea1a4689dcba5b
3.关闭6385、6386节点
# 切换目录
cd /usr/local/bin/cluster-config
redis-cli -h 127.0.0.1 -p 6385 shutdown
redis-cli -h 127.0.0.1 -p 6386 shutdown
4.springboot2.x的集成和工具类封装
4.1.引入pom.xml文件maven依赖包
基础包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 要用redis连接池 必须有pool依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
4.2.配置文件application.properties
#redis
#集群设置
#spring.redis.host=127.0.0.1
#spring.redis.port=6379
spring.redis.cluster.max-redirects=6
spring.redis.cluster.nodes=127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384
#默认0号数据库
spring.redis.database=0
#连接超时时间(毫秒)默认是2000ms
spring.redis.timeout=2000ms
# lettuce 连接池配置
#连接池最大连接数(使用负值表示没有限制) 默认为8
spring.redis.lettuce.pool.max-active=8
# 连接池中的最大空闲连接 默认为8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认为 0
spring.redis.lettuce.pool.min-idle=0
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认为-1
spring.redis.lettuce.pool.max-wait=-1ms
4.3.重写redisTemplate
增加一个redisConfig配置类
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
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;
@Configuration
public class RedisConfig {
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用Jackson2JsonRedisSerialize 替换默认的jdkSerializeable序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
4.4.封装Redis工具类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisCacheManager {
@Autowired
@Qualifier(value = "redisTemplate")
private RedisTemplate<String, Object> redisTemplate;
/**
* 指定缓存失效时间
*
* @param key
* 键
* @param time
* 时间(秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
*
* @param key
* 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key
* 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key
* 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
// ============================String=============================
/**
* 普通缓存获取
*
* @param key
* 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key
* 键
* @param value
* 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key
* 键
* @param value
* 值
* @param time
* 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
*
* @param key
* 键
* @param delta
* 要增加几(大于0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key
* 键
* @param delta
* 要减少几(小于0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
// ================================Map=================================
/**
* HashGet
*
* @param key
* 键 不能为null
* @param item
* 项 不能为null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key
* 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key
* 键
* @param map
* 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key
* 键
* @param map
* 对应多个键值
* @param time
* 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key
* 键
* @param item
* 项
* @param value
* 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key
* 键
* @param item
* 项
* @param value
* 值
* @param time
* 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key
* 键 不能为null
* @param item
* 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key
* 键 不能为null
* @param item
* 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key
* 键
* @param item
* 项
* @param by
* 要增加几(大于0)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key
* 键
* @param item
* 项
* @param by
* 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
// ============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key
* 键
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key
* 键
* @param value
* 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key
* 键
* @param values
* 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key
* 键
* @param time
* 时间(秒)
* @param values
* 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0)
expire(key, time);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key
* 键
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
*
* @param key
* 键
* @param values
* 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
// ===============================list=================================
/**
* 获取list缓存的内容
*
* @param key
* 键
* @param start
* 开始
* @param end
* 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key
* 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key
* 键
* @param index
* 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
*
* @param key
* 键
* @param value
* 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key
* 键
* @param value
* 值
* @param time
* 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key
* 键
* @param value
* 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key
* 键
* @param value
* 值
* @param time
* 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key
* 键
* @param index
* 索引
* @param value
* 值
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
*
* @param key
* 键
* @param count
* 移除多少个
* @param value
* 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}
4.5.写个测试类测试
@SpringBootTest
class ApplicationTests {
@Autowired
RedisCacheManager redisCacheManager;
@Test
void contextLoads() {
redisCacheManager.set("hello","world");
System.out.println(redisCacheManager.get("hello"));
}
}
能看完的都是大神,请大神给个关注,欢迎大家留言