算法分析 & 排序算法 & 位运算
常数操作:与数据量无关的操作
非常数操作:与数据量相关的操作
分析算法的好坏:先看时间复杂度的指标,在分析不同数据样本下的实际运行时间
比如同样的时间复杂度O(n).1000次的乘法运算和1000次的位运算,实际时间会有很大的差别
或运算 & 与运算 ^ 异或运算空间复杂度: 只需要常数个额外空间的空间复杂度为O(1)
需要额外空间的个数与数据量相关的算法的空间复杂度为O(n)
与运算(&):两个数同时为1,结果才为1,否则为0
可以用于清0,把一个数与0做与运算
取特定位置的数,把要取位置的数设置为1,其他位置设置为0,与代取数进行与运算即可
异或运算(^) : 相同得 1 ,不相同得0,还可以理解为不进位相加
或运算(|):两位中只要有1位是1,结果就是1
可以用于把某些位置置1,X = 1010 0000 ,设 Y= 0000 1111 X | Y = 1010 1111 把后四位置为1了
取反(~):0->1,1->0
异或运算的性质:1100 0011 0100 -> & 0100
0 ...
数组算法
数组二分查找二分查找的精髓在于寻找循环不变量,可以理解为有固定的含义,在处理的过程中绝对不会改变的量
二分查找服务的对象必须是有序的
二分查找的解题步骤
确定循环不变量,一般是数组的左边界和右边界
确定循环结束的条件,根据循环不变量的不同会有所改变
确定处理的逻辑
什么时候边界会改变?
要查找的是什么?
双指针法双指针法的精髓在于思考指针所表示的含义
通常有以下几种
一个指针用于遍历,另外一个指针用于收集遍历得到的数据,充当结果数组的边界
可以理解为,我们要从原来的数组中,剔除不符合要求的元素,保留符合要求的元素
不同的题目,对于双指针的操作并不相同,要根据不同的题目设计不同的逻辑
两个指针分别用于两种不同性质数组的划分
当划分为两个数组的时候,通常是解决合并的问题
要注意利用数组本身是有序的性质
不一定要从小到大,也可从大到小。
滑动窗口滑动窗口的精髓在于窗口的性质和窗口边界的变化
滑动窗口的解题步骤
确定窗口内装载的是什么东西,有什么性质
思考一种恰当的数据结构去记录这种窗口内数据的性质
确定什么时候窗口要移动
确定我们需要得到什么
模拟模拟的精髓在于模拟的 ...
Elasticsearch 进阶
首先导入hotel-admin 一个实现了对数据库数据增删改查的简易后台
本次的目标是,实现对后台数据库Crud的同时,保证ES内部的数据同步变更
明确主次关系,引起修改的主体是对数据库的Crud,通过使用消息队列技术来监听Crud,实现异步调用Es进行数据的更新
hotel-admin是Publisher,在对数据库进行crud的时候,要同步发送消息到队列
队列应该分开设计,可以使用topic交换机,分别声明,hotel.insert.queue和hotel.delete.queue队列
在添加/更新数据的时候rabbitTemplate.convertAndSend(MqConstants._HOTEL_EXCHANGE_,MqConstants._HOTEL_INSERT_KEY_,hotel.getId());
在删除数据的时候rabbitTemplate.convertAndSend(MqConstants._HOTEL_EXCHANGE_,MqConstants._HOTEL_DELETE_KEY_, ...
Elasticsearch基本操作
分布式搜索(Elasticsearch基础)
安装ES
之后还需要部署Kibana容器,因此需要让es和kibana容器互联,先创建一个网络
启动es
-e "cluster.name=es-docker-cluster":设置集群名称
-e "http.host=0.0.0.0":监听的地址,可以外网访问
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小
-e "discovery.type=single-node":非集群模式
-v es-data:/usr/share/elasticsearch/data:挂载逻辑卷,绑定es的数据目录
-v es-logs:/usr/share/elasticsearch/logs:挂载逻辑卷,绑定es的日志目录
-v es-plugins:/usr/share/elasticsearch/plugins:挂载逻辑卷,绑定es的插件目录
--privileged:授予逻辑卷访问权
--network ...
RabbitMQ初步学习
服务异步通讯(RabbitMQ)
性能下降,吞吐量下降
实际操作
RabbitMQ安装
导入tar包
启动容器
docker run \-e RABBITMQ_DEFAULT_USER=itcast \ 这是用户名-e RABBITMQ_DEFAULT_PASS=123321 \ 用户密码--name mq \ 容器名--hostname mq1 \ 主机名,集群部署的时候需要-p 15672:15672 \ 注册中心-p 5672:5672 \ 消息处理端口-d \rabbitmq:3-management
访问 192.168.81.131:15672
成功
实际操作
定义多个消费者,从而避免消息的堆积
实践开始
Work Queue 一个队列绑定多个消费者
Publisher
在1s内发送50条消息,每条消息间隔20ms避免消息发送过快
Consumer
定义了2个消费者,这2个消费者都从同一个消费队列simple.queue中拿取消息, ...
Docker基本概念
Docker
微服务的模块非常多,部署起来非常麻烦,Docker可以解决这个问题
Docker的定义
DockerFile内容
最后的 . 表示dockerfile所在的目录
构建中
构建完成
成功访问
DockerCompose 基于Compose文件进行一个集群的构建
docker-compose命令中的参数 up 代表创建并且初始化容器
使用docker-compose up -d 一键构建并且部署容器
搭建图形化docker镜像仓库
使用DockerCompose部署带有图象界面的DockerRegistry,命令如下:
version: '3.0'services: registry: image: registry volumes: - ./registry-data:/var/lib/registry ui: image: joxit/docker-registry-ui:static ports: - 8080:80 ...
分布式注册中心和服务通信
Ribbon的加载策略
饥饿加载
初次部署微服务后,第一次访问的时候,请求的周期会较长
第一次获取数据响应时间高达546ms
第二次只需要20ms
这种现象的原因是因为riobbon的懒加载机制
Nacos
首先需要导入依赖
其中父工程的依赖是为了管理子工程的依赖的版本
然后需要修改配置文件
部署成功
这样配置实现集群的划分
一切配置就绪,但是我本地上运行的时候出现了一些问题
报错 No instances available for userservice
检查错误原因
Nacos确实获取到了注册的信息,ResrTemplate也确实加入了LoadBalance注解
http://ip:8848/nacos/v1/ns/instance/list?serviceName=user-service使用该开放api访问发现cluster为空
检查发现Nacos中服务的Ip地址不是localhost/127.0.0.1,服务注册的ip使用了VMware的虚拟网络,相当于多块网卡,在进行服务注册时候,选中了VMware虚拟网络。
这个地址是我虚拟机的虚拟网卡地 ...
微服务技术栈
微服务技术栈
自动部署(持续集成)
完整的微服务技术栈
微服务本质是分布式架构方案的一种,旨在实现项目各个模块的高内聚低耦合,降低服务之间的影响,避免出现集群故障
可以通过RestTemplate来实现跨服务的远程调用(实际上就是发起一次远程的http请求)
一个服务既可以是提供者,也可以是消费者,一个服务,相对于不同服务,角色会发生变化
Eureka注册中心
编写Application启动类
编写配置文件
负载均衡
解耦合
Ribbon负载均衡
负载均衡原理
调整负载均衡策略
第一种调整方式是针对全体微服务
第二种调整方式是针对某个微服务
Java基础(一)
数据存储Java程序运行期间,有5个地方可以存储数据
寄存器:速度最快,Java没有直接控制器,根据需求进行分配
栈内存:存在于常规内存RAM中,仅次于寄存器,Java必须知道存在于栈内存中数据的生命周期,通常用于存储一些数据的引用(对象引用)
堆内存:通用的内存池,存在于RAM中,所有的Java对象都存在其中。Java不知道数据必须在堆内存中停留多长的时间,用new实例化对象的时候,会自动在堆中分配(分配与清理堆内存要比栈花费更多的时间)
常量存储:存在于程序代码中,如果需要严格保护,可以存在于ROM中
非RAM存储:数据完全存在于程序之外,在程序未运行或者脱离程序控制后依然存在。例子:① 序列化对象。② 持久化对象 。这种存储方式将对象存放于另一个介质中,并在需要时恢复成常规的,基于RAM的对象。Java 为轻量级持久化提供了支持。而诸如 JDBC 和 Hibernate 这些类库为使用数据库存储和检索对象信息提供了更复杂的支持。
基本类型存储基本类型不通过new来创建,而是使用一个自动的变量值,这个变量自动存储值,并且置于栈内存中。
基本类型
大小
最小值
最大值
包装 ...
Simply MVC FrameWork
使用反射简单模拟MVC对请求的处理过程
@WebServlet("/")public class DispatcherServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); resp.setContentType("application/json;charset=utf-8"); String path = req.getServletPath(); System.out.println("path:"+p ...