文章目录
1.多级缓存
1.客户端缓存
页面缓存,浏览器缓存,APP缓存
2.应用缓存
CDN缓存,内容分发网络:智能DNS,可以在后台设置缓存的属性:Expires,cache-control:具体某个时间点缓存到期,缓存的有效时间
3.nginx缓存
弱负载均衡为应用提供高可用性:proxy_cache_path d:/nginx-cache level=1:2
4.服务层缓存
进程外缓存:分布式缓存:REDIS
进程内缓存:Mybatis1/2级缓存,Spring缓存,Ehcache
其中nginx和CDN缓存都可以做静态资源缓存
2.为什么大厂在大表做水平分表时严禁使用自增主键
分布式下有很大问题:扩展,资源的浪费,尾部热点问题
不可以用UUID:唯一,无序。会造成大量的索引重排
雪花算法:符号位+时间戳+机器Id+序列,有序,唯一
注意时间回拨问题:把服务器上的时间人为的回调几秒
3.布隆过滤器应用
1.应用启动时候,初始化布隆
2.用户发来请求时候,判断布隆是否包含编号
2.1包含,读取redis缓存数据
2.2数据不存在,读取数据加入缓存
3.不包含返回数据不存在信息
假如商品被删除了怎么办
1.定时异步重建布隆
2.计数布隆
4.IP直连的问题以及如何解决
1.引入内部的DNS域名解析服务器:IP与域名的对照关系:没有故障发现和转移的机制,多IP只有轮询规则
2.注册中心:NACOS.Eureka,consol:支持故障发现和转移机制,多种负载均衡策略,架构复杂,会涉及为集群,考虑高可用
5.负载均衡器是什么/类型/策略
高可用,使每一台设备压力分布均匀,支持故障发现和转移
硬件负载均衡:F5
软件均衡:LVS4层代理TCP,nginx7层代理HTTP,HAProxy
4层代理相对底层,功能少,执行效率高,TCP,应用场景为实时应用集群,大规模集群数据交互
7层代理相对应用,功能多,支持资源压缩,策略多,执行效率地,HTTP,FTWEB集群
nginx负载均衡策略:轮询,权重,IP_HASH,URL_HASH,FAIR
6.为何禁用外健约束
会导致测试很不方便,保证数据完整性和一致性,级联操作方便
阿里为何不推荐使用外键约束:
1.性能问题 2.并发问题 3.级联删除使得数据不可控,触发器也严格禁用
7.慢SQL
慢查询日志记录的SQL,超过long_query_time=10
如何定位:
1.表象:1>系统级表象 2>SQL级表象 2.Mysql:慢查询日志 测试日志工具loadrunner ptquery工具
mysqldumpslow -s c slow.log
8.redis
1.避免过多的上下文切换开销
2.避免同步机制的开销
3.简单可维护
RDB:指定时间的间隔将内存中的数据快照到磁盘中dump.rdb
也就是Snaoshot快照,恢复时将快照文件读取到内存中
RDB:会单独创建一个fork进程持久化,先将数据写入到一个临时文件,持久化结束后,临时文件替换为上一个文件。
主线程是不参与IO,RDB的数据恢复速度快,但是最后一次持久化的数据可能丢失
如果是大规模的数据且数据的完整性不是很敏感的话用RDB
AOF:以日志的形式记录每个写操作,追加文件appendonly.aof
主从:读写分离和容灾备份
分片:实现扩容,分摊压力,无中心配置相对简单AP,高可用
save:只管保存,其他阻塞
bgsave:后台异步快照操作,同时可以响应客户端请求
redis4引入了多线程处理异步任务
redis6在网络模型中实现了IO多线程,工作线程只有一个
redis事务不支持回滚.mysql事务支持回滚
redis事务vspipelinevsmysql事务
redis事务为写一条积攒一条
事务执行的时期为原子的。
pipeline:先攒后发再执行
事务:先发后攒后执行
redis事务:失败了就是失败了,其他继续执行,没有回滚
少使用事务,事务的指令少和快
9.锁
悲观锁,乐观锁,自旋锁
悲观锁:坏事一点发生,所以先上锁预防
乐观锁:坏事不一定发生,所以事后补偿
自旋锁:乐观锁的实现
统一锁,分段锁
统一锁:大粒度的锁,锁定A 等待B,锁定B 等待A,A+B统一为大锁
分段锁:分为一段一段的小粒度的锁
concurrentHashMap
读写锁,独占锁,共享锁
10.oom
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
1.Java heap space
堆内存满
public static void main(String[] args){
int i = 0;
List<String> list = new ArrayList<>();
try {
while (true){
//Java heap space:堆内存
list.add(String.valueOf(i).intern());
}
}catch (Exception e){
e.printStackTrace();
}
}
2.GC overhead limit exceeded
public static void main(String[] args){
int i = 0;
List<String> list = new ArrayList<>();
try {
while (true){
//GC overhead limit exceeded大部分时间去GC了,而且GC后差不多不变,很诡异
list.add(String.valueOf(i++).intern());
}
}catch (Exception e){
e.printStackTrace();
}
}
3.Direct buffer memory
public static void main(String[] args){
//Direct buffer memory:nio引起的
//元空间不在虚拟机中,而在本地内存
//分配直接内存
ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
直接内存大于本地内存,最大直接内存=本地内存,MaxDirectMemorySize 为本地内存
4.unable to create new native thread
此oom为高并发下创造的线程过多,超过了系统极限
解决方法:
1.减少线程 2.修改linux配置,扩大默认限制
5.Metaspace
元空间满
元空间的出现就是为了解决突出的类和类加载器元数据过多导致的OOM问题
11.如何解决幂等性操作
1.防重表
数据库建立唯一性索引,可以保证最终插入数据库的只有一条数据(比如订单表对订单号进行唯一索引,所有重复提交可能产生同一个订单号的都会被拆除。当然,订单号要按你自己的设定走,一般订单号设计会是时间戳加迭代。那么如果是这样,创建仍然不能保证幂等,具体根据业务需求来判定建立的唯一索引位置
2.token
分为两个阶段,获取token和使用token。每次接口请求前先获取一个token,然后再下次请求的时候在请求的header体中加上这个token,后台进行验证,如果验证通过删除token,下次请求再次判断token。如果使用上redis缓存,流程图会是这样。
3.先查询后操作
4.支付缓冲区
把订单的支付请求都快速地接下来,一个快速接单的缓冲管道。后续使用异步任务处理管道中的数据,过滤掉重复的待支付订单。优点是同步转异步,高吞吐。不足是不能及时地返回支付结果,需要后续监听支付结果的异步返回。(一般支付都是采用这种方式)MQ.
5.悲观锁和乐观锁
悲观锁可以保证每次for update的时候其他sql无法update数据(在数据库引擎是innodb的时候,select的条件必须是唯一索引,防止锁全表)
乐观锁,一般通过version来做乐观锁,这样既能保证执行效率,又能保证幂等。例如: UPDATE tab1 SET
6.分布式锁
通过Redis做到了分布式锁,只有这次订单订单支付请求完成,下次请求才能进来。相比去重表,将放并发做到了缓存中,较为高效。
12.hashmap和hashtable得到区别
1.一个是线程同步的一个是线程非同步的
2.一个不支持空值,一个支持空值
3.一个使用Enumeration,一个使用Iterator
4.hashtable默认大小为11,增加方式为old*2+1,hashmap默认为16,增加为2的指数
5.hashtable继承Dictionary类,hashmap继承AbastarctMap
13.hashmap有哪些线程安全的方法
1.Collections.synchronizedMap()
2.concurrentHashMap
14.5种IO
1.BIO 2.NIO 3.IO multiplexing:io多路复用 4.signal driven IO:信号驱动IO 5.asynchronous IO:异步IO