由于内存大小的限制,使用一台 Redis 实例显然无法满足需求,这时就需要使用多台 Redis作为缓存数据库。但是如何保证数据存储的一致性呢,这时就需要搭建redis集群.
采用redis集群,可以保证数据分散存储,同时保证数据存储的一致性.并且在内部实现高可用的机制.实现了服务故障的自动迁移.
集群搭建
1.在Redis里准备集群文件夹
Mkdir cluster
2.在cluster文件夹中分别创建7000-7005文件夹
复制配置文件
说明:
将redis根目录中的redis.conf文件复制到cluster/7000/ 并以原名保存
cp redis.conf cluster/7000/
编辑配置文件
复制修改后的配置文件
修改端口
说明:分别将7001-7005文件中的7000改为对应的端口号的名称(需要改3处)
或者批量修改
通过脚本编辑启动/关闭指令
创建启动脚本
vim start.sh
创建关闭的脚本
vim shutdown.sh
启动脚本
sh start.sh
检查脚本是否启动正常
创建Redis集群
5.0版本执行
redis-cli --cluster create --cluster-replicas 1 192.168.126.129:7000 192.168.126.129:7001 192.168.126.129:7002 192.168.126.129:7003 192.168.126.129:7004 192.168.126.129:7005
集群测试
@Test
public void testCluster(){
Set<HostAndPort> nodes=new HashSet<>();
nodes.add(new HostAndPort("192.168.126.129",7000));
nodes.add(new HostAndPort("192.168.126.129",7001));
nodes.add(new HostAndPort("192.168.126.129",7002));
nodes.add(new HostAndPort("192.168.126.129",7003));
nodes.add(new HostAndPort("192.168.126.129",7004));
nodes.add(new HostAndPort("192.168.126.129",7005));
JedisCluster jedisCluster=new JedisCluster(nodes);
jedisCluster.set("cluster","集群测试");
System.out.println(jedisCluster.get("cluster"));
}
SpringBoot整合Redis集群
编写配置文件
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class JedisConfig {
@Value("${redis.clustesr}")
private String clustesr;
@Bean
public JedisCluster jedisCluster(){
Set<HostAndPort> nodes=new HashSet<>();
String host=null;
Integer port=null;
String[] nodesArray = clustesr.split(",");
for (String nodeArray:nodesArray
) {
host= nodeArray.split(":")[0];
port= Integer.valueOf(nodeArray.split(":")[1]);
nodes.add(new HostAndPort(host,port));
}
return new JedisCluster(nodes);
}
}
自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheFind {
public String preKey();//用户标识key的前缀
public int seconds() default 0;//如果用户不写表示不需要超时,如果写了以用户为准
}
使用注解
AOP代码实现
import com.cn.jt.annotation.CacheFind;
import com.cn.jt.util.ObjectMapperUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisCluster;
import java.util.Arrays;
/**
* @program: jt
* @description:
* @author: zhu Xia
* @create: 2020-10-14 09:32
**/@Aspect //我是一个aop的切面类
@Component//将类交给spring容器管理
public class CacheAOP {
@Autowired
private JedisCluster jedis;
/**
* 1.动态生成key preKey+用户参数数组
* @param joinPoint
* @return
*/
@Around("@annotation(cacheFind)")
public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind){
System.out.println("注解拦截");
Object result=null;
try {
//1.拼接Redis存储数据的key
Object[] args = joinPoint.getArgs();
String key = cacheFind.preKey()+"::" + Arrays.toString(args);
//2.查询redis
if(jedis.exists(key)){
//redis中有记录
String json=jedis.get(key);
//将数据转化成需要的类型——方法的返回值类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Class type = signature.getReturnType();
result = ObjectMapperUtil.toObject(json,type);
}else{
//不存在 查询数据库
result=joinPoint.proceed();//执行目标方法
//将查询结果保存到Redis中
String json= ObjectMapperUtil.toJson(result);
//判断数据是否需要超时时间
if(cacheFind.seconds()>0){
jedis.setex(key,cacheFind.seconds(),json);
}else {
jedis.set(key,json);
}
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return result;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。