1、Redis集群阐明
1.1 分片、哨兵有哪些毛病
1、分片毛病:分片的次要的性能是实现内存的扩容,然而没有高可用的成果
2、哨兵毛病:数据没有扩容,哨兵自身没有高可用机制
需要:既能够实现内存数据的扩容,同时实现高可用机制(不必第三方)
1.2 Redis集群搭建
复制Redis的redis.conf
命令:cp redis.conf cluster/7000/
批改redis.conf文件
1、正文本地绑定IP地址
2、敞开保护模式
3、批改端口号
4、启动后盾启动
5、批改pid文件
6、批改长久化文件门路
7、设定内存优化策略
8、敞开AOF模式
9、开启集群配置
10、开启集群配置文件
11、批改集群超时工夫
12、7000里的redis.conf复制到7001、7002、7003、7004、7005
13、批改
把文件7001里的redis.conf文件里的7000批改为7001
把文件7002里的redis.conf文件里的7000批改为7002
把文件7003里的redis.conf文件里的7000批改为7003
把文件7004里的redis.conf文件里的7000批改为7004
把文件7005里的redis.conf文件里的7000批改为7005
把文件内容里的7000全副改为7002
命令::%s/7000/7002/g
1、首先敞开所有的Redis服务器
2、查看配置文件编辑是否正确
3、删除多余的配置文件
4、重启redis服务器
5、搭建redis集群
执行命令:
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
编辑开启服务器脚本
开启服务 命令:sh start.sh
编辑敞开服务器脚本
命令:sh stop.sh
1.3 集群入门案例
@Test public void testCluster(){ Set<HostAndPort> sets = new HashSet<>(); sets.add(new HostAndPort("192.168.126.129", 7000)); sets.add(new HostAndPort("192.168.126.129", 7001)); sets.add(new HostAndPort("192.168.126.129", 7002)); sets.add(new HostAndPort("192.168.126.129", 7003)); sets.add(new HostAndPort("192.168.126.129", 7004)); sets.add(new HostAndPort("192.168.126.129", 7005)); JedisCluster jedisCluster = new JedisCluster(sets); jedisCluster.set("jedis", "集群赋值"); System.out.println(jedisCluster.get("jedis")); }
1.4 面试题
1、redis集群中一共能够存储16384个key???
不对的
答:16384只是槽位的数量,只负责布局这个数据归谁治理的问题,至于数据如何存储,是由redis内存决定的
2、redis集群中最多能够有多少台主机
16384台主机
3、redis中如果遇到多线程操作,是否有线程安全性问题?
没有
因为:redis服务器是单过程线程操作,每次操作都是由一个线程执行,所以不会有线程安全性问题
4、redis如何实现内存数据的优化?
LRU、LFU、随机算法、TTL
1.5 SpringBoot整合redis集群
1.5.1 编辑properties文件
阐明:将redis集群的节点写入pro配置文件中
#redis集群配置redis.nodes=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
1.5.2 编辑配置类
package com.jt.config;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import redis.clients.jedis.HostAndPort;import redis.clients.jedis.JedisCluster;import java.util.HashSet;import java.util.Set;@Configuration//标识我是配置类@PropertySource("classpath:/properties/redis.properties")public class RedisConfig { @Value("${redis.nodes}") private String nodes; //node,node,node //实现redis集群操作 @Bean public JedisCluster jedisCluster(){ Set<HostAndPort> nodeSet=new HashSet<>(); String[] nodeArray=nodes.split(","); for (String node:nodeArray) { //host:port String host=node.split(":")[0]; int port=Integer.parseInt(node.split(":")[1]); nodeSet.add(new HostAndPort(host,port)); } return new JedisCluster(nodeSet); } /* SpringBoot整合Redis分片,本质:ShardedJdeis对象,交给容器治理 */// @Bean// public ShardedJedis shardedJedis(){// List<JedisShardInfo> shards=new ArrayList<>();// String[] nodeArray=nodes.split(","); //截取// for (String node:nodeArray) { //node=ip:port// String host=node.split(":")[0]; //截取// int port=Integer.parseInt(node.split(":")[1]); //转化为int类型// //筹备分片节点信息// JedisShardInfo info=new JedisShardInfo(host,port);// shards.add(info);// }// return new ShardedJedis(shards);// }// @Value("${redis.host}")// private String host;// @Value("${redis.port}")// private Integer port;//// @Bean// public Jedis jedis(){// return new Jedis(host,port);// }}
1.5.3 编辑AOP配置
在AOP中注入Redis缓存对象
package com.jt.aop;import com.jt.anno.CacheFind;import com.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;@Aspect //标识我是一个切面@Component //交给spring容器治理public class CacheAOP { @Autowired private JedisCluster jedis; //实现集群的注入 //private ShardedJedis jedis; //实现分片对象的注入 //private Jedis jedis; /* 注意事项:当有多个参数时,joinPoint参数必须位列第一位 需要: 1、筹备key=注解的前缀 + 用户的参数 2、从redis中获取数据 有:从缓存中获取数据之后,间接返回值 没有:查询数据库之后再次保留到缓存中即可 办法: 动静获取注解的类型,看上去是注解的名称,然而本质是注解的类型,只有切入点表达式满足条件 则会传递注解对象类型 */ @Around("@annotation(cacheFind)") public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind) throws Throwable { Object result=null; //定义返回值对象 String preKey=cacheFind.preKey(); //获取key String key=preKey+"::"+ Arrays.toString(joinPoint.getArgs()); //拼接key //1、校验redis中是否有数据 if(jedis.exists(key)){ //如果数据存在,须要从redis中获取json数据,之后间接返回 String json=jedis.get(key); //获取该数据 //1、获取办法对象 2、获取办法的返回值类型 MethodSignature methodSignature= (MethodSignature) joinPoint.getSignature();//MethodSignature该办法里有获取该办法的返回值类型 //2、获取返回值类型 Class returnType=methodSignature.getReturnType(); //获取返回值类型 result=ObjectMapperUtil.toObject(json,returnType); //将JSON转化为对象 System.out.println("AOP查问缓存"); }else { //代表没有数据,须要查询数据库 result=joinPoint.proceed(); //将数据转化为JSON String json= ObjectMapperUtil.toJSON(result); //转化为JSON if (cacheFind.seconds()>0){ jedis.setex(key,cacheFind.seconds(),json); //如果有设定工夫,则执行 }else{ jedis.set(key, json); //没有设定工夫执行 } System.out.println("AOP查询数据库"); } return result; //返回该数据 }/* @Around("@annotation(com.jt.anno.CacheFind)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { //1.获取指标对象的Class类型 Class targetClass = joinPoint.getTarget().getClass(); //2.获取指标办法名称 String methodName = joinPoint.getSignature().getName(); //3.获取参数类型 Object[] argsObj = joinPoint.getArgs(); Class[] argsClass = null; //4.对象转化为class类型 if(argsObj.length>0){ argsClass = new Class[argsObj.length]; for(int i=0;i<argsObj.length;i++){ argsClass[i] = argsObj[i].getClass(); } } //3.获取办法对象 Method targetMethod = targetClass.getMethod(methodName,argsClass); //4.获取办法上的注解 if(targetMethod.isAnnotationPresent(CacheFind.class)){ CacheFind cacheFind = targetMethod.getAnnotation(CacheFind.class); String key = cacheFind.preKey() + "::" +Arrays.toString(joinPoint.getArgs()); System.out.println(key); } Object object = joinPoint.proceed(); System.out.println("盘绕开始后"); return object; }*/ //切面 = 切入点表达式 + 告诉办法 //@Pointcut("bean(itemCatServiceImpl)") //@Pointcut("within(com.jt.service.ItemCatServiceImpl)") //@Pointcut("within(com.jt.service.*)")// .*一级包门路 ..*所有子孙后代包 //@Pointcut("execution(返回值类型 包名.类名.办法名(参数列表))") //@Pointcut("execution(* com.jt.service.*.*(..))") //正文:返回值类型任意类型 在com.jt.service下的所有子孙类 以add结尾的办法,任意参数类型// public void pointCut(){// } /* 需要: 1、须要获取以后指标办法的门路 2、获取指标办法的参数 3、获取指标办法的名称 */// @Before("pointCut()")// public void before(JoinPoint joinPoint){// String classNamePath=joinPoint.getSignature().getDeclaringTypeName();// String methodName=joinPoint.getSignature().getName();// Object[] args=joinPoint.getArgs();// System.out.println("办法的门路"+classNamePath);// System.out.println("办法的名称"+methodName);// System.out.println("办法的参数"+ Arrays.toString(args));// }//// @Around("pointCut()")// public Object around(ProceedingJoinPoint joinPoint){// try {// System.out.println("盘绕告诉开始");// Object obj=joinPoint.proceed(); //如果有下一个告诉,就执行下一个告诉,如果没有就执行指标办法(业务办法)// System.out.println("盘绕告诉完结");// return obj;// } catch (Throwable throwable) {// throwable.printStackTrace();// throw new RuntimeException(throwable);// }// }}
2、京淘前台我的项目搭建
2.1 京淘架构图设计
2.2 JT-WEB我的项目创立
2.2.1 创立JT-WEB服务器
2.2.2 增加继承、依赖、插件
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <!--我的项目坐标--> <modelVersion>4.0.0</modelVersion> <artifactId>jt-web</artifactId> <!--打war包--> <packaging>war</packaging> <!--父级工程--> <parent> <artifactId>jt2007</artifactId> <groupId>com.jt</groupId> <version>1.0-SNAPSHOT</version> </parent> <!--增加依赖项--> <dependencies> <dependency> <groupId>com.jt</groupId> <artifactId>jt-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <!--增加maven插件--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
2.2.3 导入动态资源文件
阐明:将课前材料中的文件src目录导入到jt-web中
2.2.4 对于主启动类阐明
阐明:jt-web服务器启动时会加载数据源的自动化配置,然而web服务器没有配置数据源,所以报错
启动类上增加数据源启动
2.2.5 配置工作目录
2.3 域名反向代理
需要:要求用户通过http://www.jt.com拜访localhost:8092服务器
2.3.1 批改hosts文件
2.3.2 批改Nginx配置文件
#配置前台服务器 server { listen 80; server_name www.jt.com; location / { proxy_pass http://localhost:8092; } }
批改之后,重启nginx服务器
2.3.3 页面成果展示
2.4 谷歌浏览器禁用HTTPS
键入地址:
chrome://net-internals/#hsts:
批改实现之后,先清空缓存之后重启浏览器
2.5 开启后缀类型匹配
阐明: 因为京东商城的商品展示时通过
url:https://item.jd.com/100213774...
package com.jt.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class MvcConfigurer implements WebMvcConfigurer{ //开启匹配后缀型配置 @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(true); }}
URL地址小结:
1、http://www.jt.com/index 该申请会被Controller进行拦挡
2、http://www.jt.com/index.html 该申请默认条件下示意获取动态资源文件,不会被拦挡
个别条件下:Controller只拦挡前缀类型的申请. 如果须要拦挡后缀类型的申请须要独自配置
3、登录注册页面跳转
3.1 实现通用的页面跳转
url1:http://www.jt.com/user/login.... 跳转页面login.jsp
url2:http://www.jt.com/user/regist... 跳转页面register.jsp
需要: 是否利用一个Controller办法.实现通用页面的跳转?
package com.jt.config.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;@Controller@RequestMapping("user")public class UserController { /* 实现用户登录、注册页面的跳转 url1: http://www.jt.com/user/login.html 跳转页面login.jsp url2: http://www.jt.com/user/register.html 跳转页面register.jsp */ @RequestMapping("/{moduleName}") public String module(@PathVariable String moduleName){ return moduleName; }}
3.2 伪动态
伪动态是绝对实在动态来讲的,通常咱们为了加强搜索引擎的敌对性,都将文章内容生成动态页面,然而有的敌人为了实时的显示一些信息。或者还想使用动静脚本解决一些问题。不能用动态的形式来展现网站内容。然而这就损失了对搜索引擎的敌对性。怎么样在两者之间找个两头办法呢,这就产生了伪动态技术。伪动态技术是指展现进去的是以html一类的动态页面模式,但其实是用ASP一类的动静脚本来解决的。
总结:以.html结尾的一种动静页面的模式
作业
1、预习什么是跨域?
1、JSONP2、CORS形式