Redis是一个高性能的内存数据库,以key-value方式存储数据,可以作为缓存使用。
为什么持久化?Redis属于内存式数据库,程序关闭后数据会清空,有时候需要将内存中的数据长期在文件保存起来
持久化策略
AOF:默认每秒对数据进行持久化
RDB:按条件触发持久化操作(任意一个)
900 1 900秒中修改1次
300 10 300秒中修改10次
60 10000 60秒中修改10000次
配置方法
RDB
AOF
appendonly yes / no yes开启AOF
appendfsync everysec 每秒保存
如何选择?
允许少量数据丢失,性能比较高----RDB
只允许很少数据丢失----AOF
不允许数据丢失----RDB + AOF
分布式实时文件存储,可将每一个字段存入索引,使其可以被检索到。
实时分析的分布式搜索引擎。
分布式:索引分拆成多个分片,每个分片可有零个或多个副本。集群中的每个数据节点都可承载一个或多个分片,并且协调和处理各种操作;负载再平衡和路由在大多数情况下自动完成。
可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。也可以运行在单台PC上
支持插件机制,分词插件、同步插件、Hadoop插件、可视化插件等。
客户端发送请求给Gateway网关,网关将请求发送给处理器映射(HandlerMapping)
网关通过路由的匹配,将请求发送给Web处理器处理,请求就需要经过一系列过滤器
过滤器分为“pre"前置和”post"后置两种,前置过滤器实现鉴权作用,后置过滤实现性能统计或日志收集
通过过滤器到达需要的服务
一对一模型:一个生产者发送消息到一个队列,一个消费者从队列中取消息。
工作队列:工作队列,生产者将消息分发给多个消费者,如果生产者生产了100条消息,消费者1消费50条,消费者2消费50条。
生产者
发布/订阅:发布/订阅模式和Work模式的区别是:Work模式只存在一个队列,多个消费者共同消费一个队列中的消息;而发布订阅模式存在多个队列,不同的消费者可以从各自的队列中处理完全相同的消息。
路由:路由模式的消息队列可以给队列绑定不同的key,生产者发送消息时,给消息设置不同的key,这样交换机在分发消息时,可以让消息路由到key匹配的队列中。
可以想象上图是一个日志处理系统,C1可以处理error日志消息,C2可以处理info\error\warining类型的日志消息,使用路由模式就很容易实现了。
主题:主题模式和路由模式差不多,在key中可以加入通配符:
匹配.号隔开的多个单词 com.* —> com.hopu.net com.hopu com.163.xxx.xxx.xxx
左连接:左连接查询,左表的信息全部展示出来,右表只会展示符合搜索条件的信息,不足的地方记为NULL
关键字:LEFT JOIN
右连接:右连接查询,右表的信息全部展示出来,左表只会展示符合搜索条件的信息,不足的地方记为NULL
关键字:RIGHT JOIN
网关服务对所有请求进行过滤,看请求头中是否携带token,携带的话进行校验,校验成功放行,未携带token或校验失败跳转到登录页面,登录成功后使用RSA+JWT生成token,将token返回到前端页面,vue中main文件中添加全局过滤,给所有请求添加token到请求头中。
自动配置类是什么时候导入内存的 启动类上的注解:@SpringBootApplication
包含三个注解:
1.@ComponentScan 包的扫描
2.@SpringBootConfiguration 定义配置类
3.@EnableAutoConfiguration 启动自动配置(将自动配置类加载到内存)
怎么加载类到内存中? Class.forName(“完整类名”)
@EnableAutoConfiguration --> AutoConfigurationImportSelector --> loadFactoryNames —>
loadSpringFactories --> classLoader.getResources(“META-INF/spring.factories”)
在spring-boot-autoconfigure包下保存大量的自动配置类
类名都保存 META-INFO/spring.factotiries文件下
自动配置类生效需要一定条件,如@ConditionalOnClass,引入某些类时(导入了对应的框架依赖)
以Cookie作为凭证媒介
最简单的单点登录实现方式,是使用cookie作为媒介,存放用户凭证。 用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用的时候,携带上这个cookie,授权应用解密cookie并进行校验,校验通过则登录当前用户。
不难发现以上方式把信任存储在客户端的Cookie中,这种方式很容易令人质疑:
Cookie不安全
不能跨域实现免登
对于第一个问题,通过加密Cookie可以保证安全性,当然这是在源代码不泄露的前提下。如果Cookie的加密算法泄露,攻击者通过伪造Cookie则可以伪造特定用户身份,这是很危险的。 对于第二个问题,更是硬伤。
通过JSONP实现
对于跨域问题,可以使用JSONP实现。 用户在父应用中登录后,跟Session匹配的Cookie会存到客户端中,当用户需要登录子应用的时候,授权应用访问父应用提供的JSONP接口,并在请求中带上父应用域名下的Cookie,父应用接收到请求,验证用户的登录状态,返回加密的信息,子应用通过解析返回来的加密信息来验证用户,如果通过验证则登录用户。
这种方式虽然能解决跨域问题,但是安全性其实跟把信任存储到Cookie是差不多的。如果一旦加密算法泄露了,攻击者可以在本地建立一个实现了登录接口的假冒父应用,通过绑定Host来把子应用发起的请求指向本地的假冒父应用,并作出回应。 因为攻击者完全可以按照加密算法来伪造响应请求,子应用接收到这个响应之后一样可以通过验证,并且登录特定用户。
通过页面重定向的方式
最后一种介绍的方式,是通过父应用和子应用来回重定向中进行通信,实现信息的安全传递。 父应用提供一个GET方式的登录接口,用户通过子应用重定向连接的方式访问这个接口,如果用户还没有登录,则返回一个的登录页面,用户输入账号密码进行登录。如果用户已经登录了,则生成加密的Token,并且重定向到子应用提供的验证Token的接口,通过解密和校验之后,子应用登录当前用户。
这种方式较前面两种方式,接解决了上面两种方法暴露出来的安全性问题和跨域的问题,但是并没有前面两种方式方便。 安全与方便,本来就是一对矛盾。
使用独立登录系统
一般说来,大型应用会把授权的逻辑与用户信息的相关逻辑独立成一个应用,称为用户中心。 用户中心不处理业务逻辑,只是处理用户信息的管理以及授权给第三方应用。第三方应用需要登录的时候,则把用户的登录请求转发给用户中心进行处理,用户处理完毕返回凭证,第三方应用验证凭证,通过后就登录用户。
Eureka(nacos类似):Eureka service:注册中心,里面有一个注表,保Z了各个服务所在的机器和端口号,Eurake Client:负责将这个服务的信息注册到Eureka Server中。
Feign(OpenFeign类似):声明式客户端。
Ribbon:负载均衡,会帮你在每一次请求的时候选择一台机器,均匀的把请求发送到各个机器上。
Hystrix:隔离、熔断以及降级的一个框架。啥意思说白了就是Hystrix会搞很多小线程池,每个小线程池里的线程仅用去请求的服务。
默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚。
spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过
配置来捕获特定的异常并回滚
换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚
解决方案:
方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理
方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常
IK分词器:
Ik分词器就是一款中文分词器。
分词:把一段文字划分成一个个关键字,我们在搜索的时候会对自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作。
默认的中文分词会将每个字看成一个词,比如“我是天才“会被分成 我、是、天、才,这显然是不符合要求的,可能我们需要分成 我、是、天才、我是天才,所以我们需要安装Ik分词器来解决这个问题。
如果要对中文进行分词,建议使用Ik分词器。
IK分词器提供了两个分词算法。
ik_smart :最少切分。
ik_max_word:最细粒度切分。
List集合代表一个有序、可重复集合,集合中每个元素都有其对应的顺序索引。List集合默认按照元素的添加顺序设置元素的索引,可以通过索引(类似数组的下标)来访问指定位置的集合元素。
实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
Set集合与Collection的方法相同,由于Set集合不允许存储相同的元素,所以如果把两个相同元素添加到同一个Set集合,则添加操作失败,新元素不会被加入,add()方法返回false。
Map接口采用键值对Map
1)获得字符串长度
int length()
2) 对字符串进行查找
int indexOf(子字符串) 在字符串中查找字符串出现的位置,没有返回-1
int lastIndexOf(子字符串) 在字符串中查找字符串最后出现的位置,没有返回-1
3)字符串的比较
boolean equals(Object obj) 比较字符串是否相等
boolean equalsIgnoreCase(Object obj) 忽略大小写,比较字符串是否相等
boolean startsWith(String str) 判断字符串是否以该字符串开头
boolean endsWith(String str) 判断字符串是否以该字符串结尾
int compareTo(String str) 将当前字符串和其它字符串比大小,0相等,正数当前字符串大,负数其它字符串大
4)字符串的截取
String substring(int start,int end) 对字符串进行截取
String substring(int start) 从某个位置截取到末尾
char charAt(int index) 获得某个位置的字符
5) 字符串的替换
String replace(String oldString,String newString) 将字符串中某些字符串替换为新的字符串
6) 字符串的分割
String[] split(String c) 按某个字符对字符串进行分割
注意:分割的字符串可以添加\ 避免特殊符号出现错误
7) 字符串的转换
String toUpperCase() 将字符串转为大写
String toLowerCase() 将字符串转为小写
String trim() 去掉字符串前后所有的空格
8)字符串的连接 String ss = String.join(" ", strs); System.out.println(“连接后的字符串:” + ss);
Java中的属性(property),通常可以理解为get和set方法,而字段(field),通常叫做“类成员”,或 “类成员变量”,有时也叫“域”,理解为“数据成员”,用来承载数据的。
可行性分析(市场、技术、社会)
项目立项(启动大会,确定项目周期、团队、管理者)
需求分析(确定项目功能、界面等)
概要设计(架构设计、技术选型、数据库设计)
详细设计(具体功能设计、接口设计、数据库设计)
项目开发(数据库表的创建、代码的编写)
测试
上线
运维
主要用于存储对象状态为另一种通用格式,比如存储为二进制、xml、json等等,把对象转换成这种格式就叫序列化,而反序列化通常是从这种格式转换回来。
使用序列化主要是因为跨平台和对象存储的需求,因为网络上只允许字符串或者二进制格式,而文件需要使用二进制流格式,如果想把一个内存中的对象存储下来就必须使用序列化转换为xml(字符串)、json(字符串)或二进制(流)
从页面接收参数:
直接定义和表单元素name相同的参数
如果名称不一样,可以通过@RequestParam注解配置参数
通过对象进行参数绑定
通过URL的路径实现参数绑定,需要给参数添加@PathVariable注解
通过Map集合进行参数绑定
通过List集合进行参数绑定
传输数据到前台:
将数据保存到HttpServletRequest、HttpSession、ServletContext中
在参数中定义Model参数保存数据
在参数中定义Map参数保存数据
事件代理又称事件委托,是javaScript中绑定事件的常用技巧。顾名思义,‘事件代理’就是把原本需要绑定的事件委托给父元素,让父元素负责事件监听。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能
事件委托的好处:
1.减少事件数量,提高性能
2.预测未来元素,新添加的元素仍然可以触发该事件
3.避免内存外泄,在低版本的IE中,防止删除元素而没有移除事件而造成的内存溢出
存储过程是一组予编译的SQL语句
它的优点:
1.允许模块化程序设计,就是说只需要创建一次过程,以后在程序中就可以调用该过程任意次。
2.允许更快执行,如果某操作需要执行大量SQL语句或重复执行,存储过程比SQL语句执行的要快。
3.减少网络流量,例如一个需要数百行的SQL代码的操作有一条执行语句完成,不需要在网络中发送数百行代码。
4.更好的安全机制,对于没有权限执行存储过程的用户,也可授权他们执行存储
Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。SpringCloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。
1)Feign可帮助我们更加便捷,优雅的调用HTTP API。
2)在SpringCloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。
3)Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
4)SpringCloud对Feign进行了增强,使Feign支持了SpringMVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。
1、Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息
2、Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务
3、Eureka Client 会每 30s 向 Eureka Server 发送一次心跳请求,证明客户端服务正常
4、当 Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例
5、单位时间内 Eureka Server 统计到有大量的 Eureka Client 没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有上送心跳的客户端
6、当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式
7、Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地
8、服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存
9、Eureka Client 获取到目标服务器信息,发起服务调用
10、Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除
Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。
MySQL和Redis的区别以及它们的应用场景
(1)类型上 从类型上来说,mysql是关系型数据库,redis是缓存数据库
(2)作用上 mysql用于持久化的存储数据到硬盘,功能强大,但是速度较慢 redis用于存储使用较为频繁的数据到缓存中,读取速度快
(3)需求上 mysql和redis因为需求的不同,一般都是配合使用。 补充: redis和mysql要根据具体业务场景去选型 mysql:数据放在磁盘 redis:数据放在内存 redis适合放一些频繁使用,比较热的数据,因为是放在内存中,读写速度都非常快,一般会应用在下面一些场景: 排行榜、计数器、消息队列推送、好友关注、粉丝
1.新建(NEW):创建Thread类的实例时,线程进入新建状态。
2.就绪(RUNNABLE):调用线程对象的start()方法后,等待被分配给CPU时间片、谁先抢到CPU资源,谁开始执行。
3.运行(RUNNING):当就绪的线程被调用获得CPU资源时,进入运行状态,执行run()方法中的功能。
4.堵塞(BLOCKED):线程运行时出现某些原因导致正在运行的线程进入堵塞状态。
5.死亡(DEAD):线程执行完毕或被强行终止。
1.基于数据库实现排他锁
2.基于redis实现
3.基于zookeeper实现