前言
由于太长,分成两篇记录,第一篇地址: 自自技术笔记(一)
JAVA数据结构相关笔记
hashmap
数组加链表存储,通过hash计算key值直接计算出链表在数组中的下标位置,再通过遍历链表判断hash查找value
二叉树其实就是链表的加强版
Java所有集合类型
- 1.ArrayList
- 2.LinkedList
- 3.Set 只允许一个null,且是无序的
- 4.TreeSet 有序的,访问遍历比较快,底层基于TreeMap,TreeSet根据其 compare() 和 compareTo() 的定义进行排序的有序容器。
- 5.TreeMap 红黑树数据结构,有序的,非同步
- 6.HashSet 散列法,底层基于Hashmap,无序
- 7.LinkedHashSet 有序的,底层基于HashMap
- 8.HashMap
- 9.HashTable
- 10.Vector 动态数组,线程安全
注意:共10个集合类!
Hashmap扩容机制
loadFactor默认0.75,扩容时要满足一下两个条件
1、 存放新值的时候当前已有元素的个数必须大于等于阈值
2、 存放新值的时候当前存放数据发生hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)
扩容时一般成倍扩容,自jdk1.8后引入新机制
当hash碰撞的链表长度超过默认的8时自动由链表变为红黑树
注意点:如果map触发扩容会重新计算每个数据的位置,所以应尽量避免扩容
ArrayList和LinkedList
- 1.arraylist是动态数组,适合使用下标随机访问,不适合添加删除,因为添加删除要移动数据。
- 2.linkedlist是双向链表数据结构,适合添加和删除,不适合通过下标随机访问,因为他是通过移动指针一个一个节点的去遍历
- 3.linkedlist插入和删除劲量操作第一个或者最后一个效率最高。
HashMap和HashTable
- 1.hashmap基本上可以代替haahtable了
- 2.hashtable是线程安全
- 3.hashtable的迭代器不同,当迭代过程中hashtable的值被修改时会报错
- 4.HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因为contains方法容易让人引起误解。
- 5.Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。
HTTP
Http Tcp
为什么需要四次挥手
tcp之所以三次握手四次挥手是因为发送端的数据发送完了请求关闭连接,但接收端不一定接收完毕,因此需要来回重复确认。
为什么需要三次握手
如果只有两次握手,
tcp/udp属于传输层 基于 ip网络层 socket和http属于应用层
http的几种请求方式
get post put head delete connect options
trace
其中trace用于回显收到的请求,一般禁用
connect用于代理
http由几部分组成如head method keepAlive 请求url cookie host等
微服务相关
缓存穿透
当查询一个不存在的数据时,会每次都先请求缓存再请求数据库,由此造成性能浪费和攻击漏洞
解决方案1,直接缓存空数据,设置短时间过期
解决方案2,布隆过滤器,将所有可能存在的数据的哈希保存下来,每次请求时判断哈希是否存在
缓存雪崩
同一时间大量缓存失效造成服务器压力暴增,解决方案:失效时间加上随机数保证每个缓存的失效时间不一样
缓存击穿
一些热点数据可能正好在缓存失效时出现大量请求导致数据库压力剧增,解决方案:
- 1.分布式锁
- 2.提前续期,在发现该缓存快要过期时续期并锁住,然后重新从数据库查询最新数据
- 3.后台线程定时更新缓存
Cap理论
- C.一致性(Consistency),某一节点更新数据后,其他节点都能读取到最新数据
- A.可用性(Availability),每一个请求都能得到响应,无需确保返回的数据为最新
- P.分区容错性(Partition tolerance),当服务被分散在各个孤立的区域,而区域之间相互无法通信时,系统照样能够工作
Cap三者无法同时满足,只能取其二。
1.当大量服务分散部署到各个省,且合省之间相互独立,其他省服务器宕机不影响本省服务继续提供支持时,选择ap
2.对于其他情况则只需保证ca即可,一般情况下没有分区性问题。
一致性hash
一致性hash的作用是解决数据倾斜问题,保证请求和数据分布均匀。
整个Hash空间被构建成一个首尾相接的环,使用一致性Hash时需要进行两次映射。
第一次给每个节点计算哈希并记录它们在环上的位置,第二次给每个Key计算Hash,然后沿着顺时针的方向找到环上的第一个节点,就是该Key储存对应的集群
源码问答
为了应对该死的面试而记录的
1.Spring注入私有属性开关
2.spring boot自动加载原理
3.spring扫描原理 ,读取class文件反射
spring循环注入问题
spring为避免循环注入 spring用了三级缓存分别为:
- singletonFactories : 单例对象工厂的cache
- earlySingletonObjects :提前暴光的单例对象的Cache
- singletonObjects 单例对象缓存,逐步从缓存中获取,未创建完的对象放提前曝光对象cache里,通过对象引用传递解决循环依赖问题当对象创建完成后会从缓存中移出,属性注入通过后置处理器注入
spring cloud ribbon 7种负载均衡策略
- 1.轮询
- 2.随机
- 3.最大可用策略(过滤不可用选择并发数最小的)
- 4.可用过滤(过滤并发大于阈值的再轮询)
- 5.加权轮询
- 6.重试策略(配置时间段内访问不成功则一直尝试使用subRule方式重试 )
- 7.区域感知策略(先使用主过滤条件,判断最小过滤数和最小过滤百分比,满足条件的服务才使用)
- 8.令牌桶(也就是ip绑定)
分表算法
1.按时间分表
2.按数字,如分30张表使用id %30 得出的结果为表的位置
3.使用md5值的前5位做hash
@enableEurekaClient只能用于注册中心为eureka而@enableDiscoveryClien则支持其他注册中心
高可用策略
服务降级 自动重试 快速失败(熔断)
负载均衡 健康检测 回退部署
服务降级
暂时关闭不重要的服务 分级降级 降级权重
微服务概念理解
1.将业务服务拆分成多个细小独立的服务
2.每个微服务都是独立可运行的
3.微服务本质是soa(面向服务架构)其是一种架构设计理念
微服务的好处
1.每个服务独立运行不受技术,数据库,等影响
2.由于其划分精细,小部分功能升级不影响其他功能使用
3.松耦合
4.接口通用
spring cloud组件
1.eureka
2.ribbon
3. feign
4.config
5.hystrix
6. bus消息总线
7.dashbord(hystrix仪表盘)
8.Zuul网关
9.sleuth调用链追踪(一般配合zipkin)
高并发策略
1.线程池
2.负载均衡
3.熔断
4.队列
5.服务降级
实现高并发秒杀的三种思路
1.数据库行锁(性能差)
2.使用redis的list存储秒杀数据使用lpop删除数组中的第一个下标的数据来表示减少库存,redis是单线程的 (性能最好)
3.使用redis分布式锁,通过setnx方法获取锁,setnx是设置一个值,如果它不存在则设置成功返回1,否则失败返回0,再通过expire设置锁的超时时间,避免死锁,最后需要操作完后根据客户端请求唯一标识删除锁(为了避免误删)
redis相关
redis优势
- 1.单线程与上下文切换消耗
- 2.多路复用io模型,非阻塞io
- 3.基于内存操作,hashmap时间复杂度是o(1)
- 4.redis实现了自己的vm机制
redis哨兵模式有三种
故障转移 投票选举 监控
epoll
io复用模型中的一种,为每一个流增加标记,这样重缓冲区读取流时就知道当前流的状态了,在获取到流之前处于阻塞状态类似socket
select所有流轮询,限制大小为1024,其优势有:
- 1.没有并发限制,上限是最大可打开文件数目,这个数目和系统内存关系很大
- 2.select代理网络io,无差别轮询,遍历所有流的io事件,去过有流发生了io事件则唤醒线程去处理,时间复杂度为o(n)
redis数据淘汰策略
- 1.当内存达到限制的值且尝试使用更多的内存时。
- 2.回收最少使用的键
- 3.回收最少使用的键,但是仅仅从过期的集合中回收
- 4.随机回收
- 5.随机回收过期集合中的键
- 6.从过期集合中优先回收存活时间简短的键
Redis持久化
- 1.rdb策略,定时持久化,将当前内存数据保存,优点是效率高,持久化数据是单个文件,备份恢复简单,缺点是数据丢失过大
- 2.aof策略,每秒备份,也就是不停地望持久化数据库中追加数据,优点是宕机时丢失数据少,缺点是效率不如rdb
- 本文作者: reiner
- 本文链接: https://reiner.host/posts/8deaf922.html
- 版权声明: 转载请注明出处,并附上原文链接