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;
@Configuration
public 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、JSONP
2、CORS形式
发表回复