Redis集群搭建,以及SpringBoot实现

一、思路

  • Java Redis实现程序设计
  • Redis集群架构图
概念特别说明:
1、redis集群:
针对redis服务器搭建部署而言,多个redis-server构建一个redis集群环境,对外提供redis服务。key根据redis内部策略(主要是Hash 虚拟槽分区 slot),分配到不同的redis-server服务器中
2、redis主从同步:
为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。为此, Redis 提供了复制(replication)功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。
3、区别:
主从服务器分工明确,主服务器用来写,从服务器用来读,一个主服务器,多个从服务器;集群就好比,多个主从服务器,比如:全国有多个主从服务器,分别处理各自区域的信息,这样可以减少单个主从服务器中主服务器的压力
4、slot特别说明
哈希槽的存在,是为了能快速找到key所在的节点。一个redis集群包含2^16=16384个哈希槽,会分配给各个节点。可以通过槽的分配来控制不同节点的数据量和请求数。哈希槽通过顺时针来分片,即一个节点顺时针到下一个几点之间的槽属于下一个节点。
每一个key,通过公式slot=CRC16(key)/16384来计算属于哪个槽。
 
 
Redis集群搭建,以及SpringBoot实现
Redis集群搭建,以及SpringBoot实现

二、Redis集群部署具体实现

1、环境说明
本次Redis集群搭建部署是基于Windows开发环境
 
2、服务器规划
节点1:
127.0.0.1:6379  主   ok
127.0.0.1:6380  从   ok
 
节点2:
127.0.0.1:6479  主
 
节点3:
127.0.0.1:6579  主
 
3、部署步骤
(1)安装Redis
 
可以直接下载最近稳定版本的zip文件,无需进行安装,文件下载解压到目录:G:\MyPrivate\MyKit\Redis-x64-3.0.504
Redis集群搭建,以及SpringBoot实现
 
Redis集群搭建,以及SpringBoot实现
 
 
(2)修改Redis配置文件
 
A、以6379端口配置文件redis.windows.conf为例,其他端口6479配置文件redis.windows6479.conf、端口6579配置文件redis.windows6579.conf雷同
 
B、修改配置文件,关闭rdb内存快照方式,开启aof持久化方式,开启cluster
port 6379
 
#关闭rdb
#save 900 1
#save 300 10
#save 60 10000
dbfilename dump6379.rdb
 
#开启aof
appendonly yes
appendfilename "appendonly6379.aof"
appendfsync everysec
 
#配置集群信息
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
cluster-slave-validity-factor 10
cluster-migration-barrier 1
cluster-require-full-coverage yes
 
(3)启动Redis服务器
依次打开Dos窗口,切换到Redis安装目录cd G:\MyPrivate\MyKit\Redis-x64-3.0.504
执行命令:
redis-server.exe redis.windows.conf
redis-server.exe redis.windows6380.conf
redis-server.exe redis.windows6479.conf
redis-server.exe redis.windows6579.conf
 
Redis集群搭建,以及SpringBoot实现
 
 
(4)下载并安装Ruby,下载地址:http://railsinstaller.org/en
  设置系统环境变量,把C:\RailsInstaller\Ruby2.3.3\bin添加到系统环境变量中
Redis集群搭建,以及SpringBoot实现
 
 
Redis集群搭建,以及SpringBoot实现
 
(5)安装完毕之后,下载Ruby环境下Redis的驱动,考虑到兼容性,这里下载的是3.2.2版本,下载地址: https://rubygems.org/gems/redis/versions/3.2.2
下载完毕放置Redis安装目录下G:\MyPrivate\MyKit\Redis-x64-3.0.504\redis-3.2.2.gem
 
Redis集群搭建,以及SpringBoot实现
(6)安装Ruby Redis驱动
gem install --local G:\MyPrivate\MyKit\Redis-x64-3.0.504\redis-3.2.2.gem
 
(7)下载Redis官网提供的Redis集群Ruby脚本redis-trib.rb,有两种方式:
 
下载的文件放在Redis安装目录下
 
(8)创建Redis集群
打开Dos窗口,进入到Redis安装目录 G:\MyPrivate\MyKit\Redis-x64-3.0.504,执行:ruby redis-trib.rb create --replicas 0 127.0.0.1:6379 127.0.0.1:6479 127.0.0.1:6579,当出现提示的时候,手动输入yes
Redis集群搭建,以及SpringBoot实现
 
校验是否创建成功,输入命令:ruby redis-trib.rb check 127.0.0.1:6379
Redis集群搭建,以及SpringBoot实现
 
 
补充: redis-trib.rb命令
支持的操作如下:
1. create:创建集群
2. check:检查集群
3. info:查看集群信息
4. fix:修复集群
5. reshard:在线迁移slot
6. rebalance:平衡集群节点slot数量
7. add-node:添加新节点
8. del-node:删除节点
9. set-timeout:设置节点的超时时间
10. call:在集群所有节点上执行命令
11. import:将外部redis数据导入集群
 
 
添加slave节点
给127.0.0.1:6379添加slave节点127.0.0.1:6380,命令如下所示。
注意:slave节点的特性,数据来自于主节点,可以进行读写操作,写操作默认都会在Master节点上面进行处理
 
G:\MyPrivate\MyKit\Redis-x64-3.0.504>ruby redis-trib.rb add-node --slave 127.0.0.1:6380 127.0.0.1:6379
>>> Adding node 127.0.0.1:6380 to cluster 127.0.0.1:6379
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: d2d52e9453b367a96ad0b89973851efbb0452c08 127.0.0.1:6379
   slots:0-5460 (5461 slots) master
   0 additional replica(s)
M: 36863046950bc37bd6462a6c977135f8d7c01449 127.0.0.1:6479
   slots:5461-10922 (5462 slots) master
   0 additional replica(s)
M: 9fa742639b82a080ac168b9a6c1943b54977371c 127.0.0.1:6579
   slots:10923-16383 (5461 slots) master
   0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Automatically selected master 127.0.0.1:6379
>>> Send CLUSTER MEET to node 127.0.0.1:6380 to make it join the cluster.
Waiting for the cluster to join...
>>> Configure node as replica of 127.0.0.1:6379.
[OK] New node added correctly.
 
G:\MyPrivate\MyKit\Redis-x64-3.0.504>ruby redis-trib.rb check 127.0.0.1:6379
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: d2d52e9453b367a96ad0b89973851efbb0452c08 127.0.0.1:6379
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
M: 36863046950bc37bd6462a6c977135f8d7c01449 127.0.0.1:6479
   slots:5461-10922 (5462 slots) master
   0 additional replica(s)
S: d07c74d1bbdca97340867bed535259c4688a877d 127.0.0.1:6380
   slots: (0 slots) slave
   replicates d2d52e9453b367a96ad0b89973851efbb0452c08
M: 9fa742639b82a080ac168b9a6c1943b54977371c 127.0.0.1:6579
   slots:10923-16383 (5461 slots) master
   0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
 
G:\MyPrivate\MyKit\Redis-x64-3.0.504>ruby redis-trib.rb info 127.0.0.1:6379
127.0.0.1:6379 (d2d52e94...) -> 3 keys | 5461 slots | 1 slaves.
127.0.0.1:6479 (36863046...) -> 5 keys | 5462 slots | 0 slaves.
127.0.0.1:6579 (9fa74263...) -> 3 keys | 5461 slots | 0 slaves.
[OK] 11 keys in 3 masters.
0.00 keys per slot on average.
 
 
4、测试验证
(1)进入任一集群节点,可以通过cluster info 查询集群节点状态
 
C:\Users\jiangjiabao>G:
 
G:\>cd G:\MyPrivate\MyKit\Redis-x64-3.0.504
 
G:\MyPrivate\MyKit\Redis-x64-3.0.504>redis-cli.exe -c -p 6379
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:3
cluster_size:3
cluster_current_epoch:3
cluster_my_epoch:1
cluster_stats_messages_sent:619
cluster_stats_messages_received:614
127.0.0.1:6379> info cluster
# Cluster
cluster_enabled:1
 
(2)设置key,切换到不同的集群节点查询key
127.0.0.1:6379> set name yubing
-> Redirected to slot [5798] located at 127.0.0.1:6479
OK
127.0.0.1:6479> set age 39
-> Redirected to slot [741] located at 127.0.0.1:6379
OK
127.0.0.1:6379> set height 171
-> Redirected to slot [8223] located at 127.0.0.1:6479
OK
127.0.0.1:6479> hset 1004user name yubing
(integer) 1
 
 
127.0.0.1:6479> get name
"yubing"
127.0.0.1:6479> get age
-> Redirected to slot [741] located at 127.0.0.1:6379
"39"
127.0.0.1:6379> mgetall 1004user
(error) ERR unknown command 'mgetall'
127.0.0.1:6379> hgetall 1004user
-> Redirected to slot [10116] located at 127.0.0.1:6479
1) "name"
2) "yubing"
 

三、Java SpringBoot之Redis集群实现

 
1、代码结构如下所示
Redis集群搭建,以及SpringBoot实现
 
2、代码说明
(1)pom.xml添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--lettuce pool 缓存连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
 
<!--springboot 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
 
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
 
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.66</version>R
</dependency>
 
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
 
application.properties配置文件
spring.application.name=exec-data-redis
server.port=8081
 
#redis连接配置型
spring.redis.database=0
#spring.redis.host=127.0.0.1
#spring.redis.port=6379
#spring.redis.password=
 
#redis jedis配置信息
##连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
##连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
##连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
##连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
##连接超时时间(毫秒)
spring.redis.timeout=1000
 
spring.redis.cluster.nodes=192.168.8.196:6379,192.168.8.196:6479,192.168.8.196:6579,192.168.8.196:6380
spring.redis.cluster.max-redirects=2
 
 
#redis lettuce方式配置信息
#spring.redis.lettuce.pool.max-active=8
#spring.redis.lettuce.pool.max-wait=-1
#spring.redis.lettuce.pool.max-idle=8
#spring.redis.lettuce.pool.min-idle=0
 
 
(2)RedisConfig.java
package com.darben.execdatareids.config;
 
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
 
/**
* @Desc redis配置
* @Date 2020-03-09
* @Author Darben
*/
@Configuration
@EnableCaching
public class RedisConfig {
 
/**
*@Description:
*@Param:
*@return: org.springframework.data.redis.core.RedisTemplate<java.lang.String,java.lang.Object>
*@date: 2020/3/9
*/
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
 
RedisTemplate<String,Object> template = new RedisTemplate<>();
//配置连接工厂
template.setConnectionFactory(factory);
 
//使用Jackson2JsonRedisSerializer来序列化和反序列化redisvalue值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
 
ObjectMapper om = new ObjectMapper();
//指定要序列化的域,field,getset,以及修饰符范围,ANY是都有包括privatepublic
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jsonRedisSerializer.setObjectMapper(om);
 
template.setValueSerializer(jsonRedisSerializer);
template.setKeySerializer(new StringRedisSerializer());
 
template.setHashValueSerializer(jsonRedisSerializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
 
return template;
}
 
/*@Bean
public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
 
RedisTemplate<String,Object> template = new RedisTemplate<>();
//配置连接工厂
template.setConnectionFactory(factory);
 
//使用Jackson2JsonRedisSerializer来序列化和反序列化redisvalue值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
 
ObjectMapper om = new ObjectMapper();
//指定要序列化的域,field,getset,以及修饰符范围,ANY是都有包括privatepublic
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jsonRedisSerializer.setObjectMapper(om);
 
template.setValueSerializer(jsonRedisSerializer);
template.setKeySerializer(new StringRedisSerializer());
 
template.setHashValueSerializer(jsonRedisSerializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
 
return template;
}*/
 
/*以下Bean可以直接注入到Service中使用*/
 
/**
*@Description: Redis字符串型操作
*@Param:
*@return:
*@date: 2020/3/9
*/
@Bean
public ValueOperations<String,Object> valueOperations(RedisTemplate<String,Object> redisTemplate){
return redisTemplate.opsForValue();
}
 
/**
*@Description: List型操作
*@Param:
*@return:
*@date: 2020/3/9
*/
@Bean
public ListOperations<String,Object> listOperations(RedisTemplate<String,Object> redisTemplate){
return redisTemplate.opsForList();
}
 
/**
*@Description: 无序集合行操作
*@Param:
*@return:
*@date: 2020/3/9
*/
@Bean
public SetOperations<String,Object> setOperations(RedisTemplate<String,Object> redisTemplate){
return redisTemplate.opsForSet();
}
 
/**
*@Description: 有序集合行操作
*@Param:
*@return:
*@date: 2020/3/9
*/
@Bean
public ZSetOperations<String,Object> zSetOperations(RedisTemplate<String,Object> redisTemplate){
return redisTemplate.opsForZSet();
}
 
/**
*@Description: hash行操作
*@Param:
*@return:
*@date: 2020/3/9
*/
@Bean
public HashOperations<String,String,Object> hashOperations(RedisTemplate<String,Object> redisTemplate){
return redisTemplate.opsForHash();
}
 
}
 
(3)RedisUtils.java
 
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
 
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
 
/**
* @description: Redis类组
* @author: darben
* @create: 2020-03-09 15:39
*/
@Component
@Slf4j
public class RedisUtils {
 
@Autowired
private RedisTemplate<String,Object> redisTemplate;
 
public RedisUtils(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
 
/**
*@Description:
*@Param:
* key key
* time 失效时间位秒
*@return:
*@date: 2020/3/9
*/
public boolean expire(String key,long time){
try {
if (time>0){
redisTemplate.expire(key,time, TimeUnit.SECONDS);
}
return true;
}
catch (Exception e){
log.error("-> 设置redis key失效时间异常 "+ e);
e.printStackTrace();
return false;
}
}
 
/**
*@Description: 查询ke时间
*@Param:
*@return: 时间() 返回0代表永久有效
*@date: 2020/3/9
*/
public long getExpire(String key){
return redisTemplate.getExpire(key,TimeUnit.SECONDS);
}
 
/**
*@Description:
*@Param: 集合,多一起
*@return:
*@date: 2020/3/9
*/
public void delKeys(String ... key){
if(key!=null && key.length>0){
if(key.length == 1){
redisTemplate.delete(key[0]);
}
else{
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
 
/**
*@Description:
*@Param: 单个进
*@return:
*@date: 2020/3/9
*/
public boolean del(String key){
if(!StringUtils.isEmpty(key)){
return redisTemplate.delete(key);
}
return true;
}
 
/**
*@Description: 持久化key
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean persist(String key){
return redisTemplate.persist(key);
}
 
//String结构类型处理
//..
 
/**
*@Description: 普通
*@Param:
*@return:
*@date: 2020/3/9
*/
public Object get(String key){
return StringUtils.isEmpty(key)?null:redisTemplate.opsForValue().get(key);
}
 
/**
*@Description: 普通存存
*@Param:
*@return:
*@date: 2020/3/9
*/
public boolean set(String key,Object value){
try {
redisTemplate.opsForValue().set(key,value);
return true;
}
catch (Exception e){
log.error("->set occur error "+e);
e.printStackTrace();
return false;
}
}
 
/**
*@Description: 普通存存+时间
*@param key
*@param value
*@param time 时间() time要大于0 如果time小于等于0 将设置无限期
*@return:
*@date: 2020/3/9
*/
public boolean set(String key,Object value,long time){
try {
redisTemplate.opsForValue().set(key,value,time,TimeUnit.SECONDS);
return true;
}
catch (Exception e){
log.error("->set occur error "+e);
e.printStackTrace();
return false;
}
}
 
/**
*@Description: incrby
*@Param:
*@return:
*@date: 2020/3/11
*/
public long incrby(String key,long delta){
if(delta<0){
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key,delta);
}
 
/**
*@Description: decryb 递减
*@Param:
*@return:
*@date: 2020/3/11
*/
public long decrby(String key,long delta){
if(delta<0){
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().decrement(key,-delta);
}
 
//list链表结构类型处理
//..
 
/**
*@Description: 查询key对应list存的
*@Param:
*@return:
*@date: 2020/3/11
*/
public List<Object> lGet(String key,long start,long end){
try {
return redisTemplate.opsForList().range(key,start,end);
}
catch (Exception e){
log.error("lGet occur error. "+e);
e.printStackTrace();
return null;
}
}
 
/**
*@Description: 查询List对应
*@Param:
*@return:
*@date: 2020/3/11
*/
public long lGetListSize(String key){
try {
return redisTemplate.opsForList().size(key);
}
catch (Exception e){
log.error("lGetListSize occur error."+e);
e.printStackTrace();
return 0;
}
}
 
/**
*@Description: 索引list中的
*@Param:
*@return:
*@date: 2020/3/11
*/
public Object lGetByIndex(String key,long index){
try {
return redisTemplate.opsForList().index(key,index);
}
catch (Exception e){
log.error("lGetByIndex occur error. "+e);
e.printStackTrace();
return null;
}
}
 
/**
*@Description: 将数据存list
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean rPush(String key,Object value){
try {
redisTemplate.opsForList().rightPush(key,value);
return true;
}
catch (Exception e){
log.error("rPush occur error. "+ e);
e.printStackTrace();
return false;
}
}
 
/**
*@Description:
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean rPush(String key,Object value,long time){
try {
redisTemplate.opsForList().rightPush(key,value);
if(time > 0){
expire(key,time);
}
return true;
}
catch (Exception e){
log.error("rPush with expire occur error. "+ e);
e.printStackTrace();
return false;
}
}
 
/**
*@Description: list行存
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean rPush(String key,List<Object> list){
try {
redisTemplate.opsForList().rightPushAll(key,list);
return true;
}
catch (Exception e){
log.error("rPushAll occur error. "+ e);
return false;
}
}
 
/**
*@Description: list行存+时间
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean rPush(String key,List<Object> list,long time){
try {
redisTemplate.opsForList().rightPushAll(key,list);
if(time>0){
expire(key,time);
}
return true;
}
catch (Exception e){
log.error("rPushAll occur error. "+ e);
return false;
}
}
 
/**
*@Description: 根据索引修改list中的某条数
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean lUpdateIndexValue(String key,long index,Object value){
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
log.error("lUpdateIndexValue occur error."+e);
e.printStackTrace();
return false;
}
}
 
 
//HashMap结构类型处理
//..
 
/**
*@Description: key对应map指定profile
*@Param:
*@return:
*@date: 2020/3/11
*/
public Object hGet(String key,String profile){
return redisTemplate.opsForHash().get(key,profile);
}
 
/**
*@Description: key对应Hash
*@Param:
*@return:
*@date: 2020/3/11
*/
public Map<Object,Object> hMget(String key){
return redisTemplate.opsForHash().entries(key);
}
 
/**
*@Description: 储值HashMap
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean hMset(String key,Map<String,Object> map){
try {
redisTemplate.opsForHash().putAll(key,map);
return true;
}
catch (Exception e){
log.error("->hmset occur error "+e);
e.printStackTrace();
return false;
}
}
 
/**
*@Description: HashMap + 时间
*@Param:
*@return:
*@date: 2020/3/11
*/
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){
log.error("->hmset with expire time occur error "+e);
e.printStackTrace();
return false;
}
}
 
/**
*@Description: 向一hash表中放入,如果不存在将创
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean hSet(String key,String profiel,Object value,Long time){
try{
redisTemplate.opsForHash().put(key,profiel,value);
if(time !=null && time.longValue()>0){
expire(key,time);
}
return true;
}
catch (Exception e){
log.error("->hset with expire time occur error "+e);
e.printStackTrace();
return false;
}
}
 
/**
*@Description: Hash表中的
*@Param:
*@return:
*@date: 2020/3/11
*/
public void hDel(String key,Object ... profile){
redisTemplate.opsForHash().delete(key,profile);
}
 
/**
*@Description: hash表中是否有key
*@Param:
*@return:
*@date: 2020/3/11
*/
public boolean hHasKey(String key,String profile){
return redisTemplate.opsForHash().hasKey(key,profile);
}
 
 
}