1. ·······················
LRU(最近最久未使用)和LFU(最近最少使用)
幂等性问题接口
调表
IO多路复用
奇安信
网易1
网易2021提前
Redis-从海量数据里查询某一固定前缀(k1)的key
1.keys k1* 一次性返回数据量太大
2.scan 增量迭代式的命令,
scan 0 MATCH 11* 因为这里没有指定count,所以默认为10
scan 176 MATCH 11* COUNT 1000
limit a,b
limit 3,2 第几个位置开始索引,索引位置从0开始计算。第二个参数是取记录个数【4,5两个记录】
四种隔离级别怎么实现的(锁+Mvcc实现的)
读未提交: select语句不加锁,每次都是最新的数据
写加行锁
读已提交:
select 使用mvcc的快照读,生成readview时机不同
修改操作使用行锁
可重复读:
select mvcc快照读
修改 使用临检锁(行锁+间隙锁)
串行化:读写都会加锁
重写Arrays.sort方法 比较两个String字符串 使用的compareTo比较 数字可直接使用- 进行比较
Arrays.sort(cur,(String a, String b)->{
return (a+b).compareTo(b+a);
});
//字符串按照字母排序 先toCharArray() 然后Arrays.sort(); 之后使用new String 即可完成排序
String s="sdsa";
char [] chs = s.toCharArray();
Arrays.sort(chs);
s = new String(chs);
//trim 去掉收尾空格 split以什么分割开
String[] intern = s.trim().split(" ");
threadlocal 使用开放地址法 - 线性探测法:当前哈希槽有其他对象占了,顺着数组索引寻找下一个,直到找到为止
hashset 中调用 hashmap 来存储数据的,hashmap 采用的链地址法:当哈希槽中有其他对象了,使用链表的方式连接到那个对象上
ThreadLocalMap中使用开放地址法来处理散列冲突,而HashMap中使用的是分离链表法。之所以采用不同的方式主要是因为:在ThreadLocalMap中的散列值分散得十分均匀,很少会出现冲突。
并且ThreadLocalMap经常需要清除无用的对象,使用纯数组更加方便。
ThreadLocalMap通过key(ThreadLocal类型)的hashcode来计算数组存储的索引位置i。如果i位置已经存储了对象,那么就往后挪一个位置依次类推,直到找到空的位置,再将对象存放。另外,在最后还需要判断一下当前的存储的对象个数是否已经超出了阈值(threshold的值)大小,如果超出了,需要重新扩充并将所有的对象重新计算位置。
HashSet是怎么去重的
根据key获得hash值 然后取余数组长度 获得数组下标,为null的话直接加入,不为null的话equals比较,相同就不存进去,不同直接存入 链表
拉链法解决hash冲突
union将两个查询结果去重保存
union all 不去重保存
CROSS JOIN生成笛卡尔积
inner join 相等查询
left join 左连接
hashmap怎么删除元素?
remove 方法
两个join某些情况都可以使用
装箱 Integer.valueOf()
Integer.parseInt(String的);
为什么b+数 不用红黑树 io次数为什么少(多叉平衡树)
1.b+树 非叶子节点只存储索引,叶子结点存储内容 ,同样的一个磁盘页可以存更多的数据(每页16kb,每个节点就是一个内存页16kb),磁盘io次数更少 是个多路平衡树
b树 非叶子结点也存储数据 所以说存的数据更少 层数更多 磁盘io更多
叶子结点有个双向指针只需要扫一遍即可 b树还需要去中序遍历查询
2.b+树磁盘io固定的而更加稳定 红黑树和b树不稳定 层数会更多
3.b+树是多路平衡树,红黑树是二叉树 所以b+树io次数会更少
4.不用hash索引,hash底层使用的哈希表实现的等值查询,不能排序的操作,可能hash冲突
覆盖索引:就是查询的字段在索引上直接查出来,不需要回表的操作,回表的操作就是在二级索引查到了主键id(索引值)然后去主键索引查具体的数据行
当前会议udp 头部 还有怎么控制的udp当前会议的实时性 udp 头部 源端口 目的端口 长度 检验和
源端口 目的端口 长度 校验和
读已提交和可重复读都是使用MVCC实现的并发控制
怎么实现的并发控制
readview+undolog版本链
实现这个 区别在readview的生成时机不同
读已提交:每次select都会创建新的readview 保证读取到已提交的修改
可重复读:在一个事务范围内,只有在第一次select的时候会更新这个readview,以后不在更新这个复用这个readview
可重复读使用的mvcc实现的幻读
没有完全解决:两个快照读中间加个当前读就会出现幻读的情况 ,更新(当前读)使mvcc版本失效了,出现了幻读
开始查询 然后另外一个修改了数据行,当前再去修改的话 在查询就是出现了幻读
nacos feign的底层协议(对http协议的一种封装)
解决接口的幂等性:
1.使用token字段放入redis
2.唯一id(比如自己的手机号)[会访问db 效率问题]
3.乐观锁加个version字段[先查版本号 然后并发修改 肯定只能一个成功]
4.可以设置状态字段保证幂等性(比如项目中的延迟队列中的解锁库存 必须判断库存表处于锁定状态而且订单处于关闭状态)
解决hash冲突:
1.开放地址法(线性探测和二次探测)
2.链地址法
3.再hash法
1.算法
2.rabbitmq知识点
3.项目复习
4.os重要知识点
redis中的大key 怎么解决
1.比如String类型的把它分为几个key 分开
2.hash的话就是把当前对象属性都分布到field上 取的时候只取需要的字段 防止取的数据量太大 阻塞主主线程的使用
exist 和 in
exist 内大好
in 外大好
exist的话首先计算外表 然后带入内循环依次判断是否正确
in首先遍历里边的sql 生成一个表 然后去匹配外边的数据
int 1 和 int 10的区别
数字和存储空间无关 都是4byte
int(数字) 只有跟zerofill结合 才能展示准确的位数 否则显示都出不来{少于这个时可以在前边补上,超过了按照原样输出}
如何避免全表扫描
1.就是索引失效的情况
避免使用or时左右没有索引
避免使用like% %
避免使用《》 !=
避免使用索引列进行计算
避免索引列为char类型的=后边不适用‘’
不符合最左前缀原则的
约定大于配置
就是原来有一些固定的约定,如果不使用这些约定的话 可以自己设置替换他 尽可能的减少了默认配置
创建一个spring注解
@Target({ElementType.METHOD,ElementType.FIELD}) //用在什么地方 一般用在方法
@Retention(RetentionPolicy.RUNTIME) //运行时运行
public @interface zhujie {
String value() default "";
}
对象头三部分
头部(有个threadid在synchronized修改的时候去使用
有个4个bit位存储 标识年轻代晋升老年代的年龄阈值字段(jvm的分代年龄) )+实例变量+填充字节
```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
mysql的分层 连接层 服务层 存储引擎层
```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
各种bufferpool 和 changebuffer write buffer
bufferpool 是innodb存储殷勤的缓冲池,不属于mysql的server层,主要存储数据页和(写缓冲)changebuffer,用来存储变更记录
如果每次写操作,数据库都直接更新磁盘中的数据,会很占磁盘IO。为了减少磁盘IO,InnoDB在Buffer Pool中开辟了一块内存,用来存储变更记录,为了防止异常宕机丢失缓存,当事务提交时会将变更记录持久化到磁盘(redo log),等待时机更新磁盘的数据文件(刷脏),用来缓存写操作的内存,就是Change Buffer
唯一索引和普通索引怎么选择
普通索引可以重复,唯一索引只能是唯一的一个可以为空
主键索引不能为空,因为他就是聚簇索引排列的,这也就是为啥主键不能为null
如果是查询操作的话,查询会以页为单位将数据页加载进内存,bufferpool缓冲池
唯一索引根据条件查询到等值记录直接返回
普通索引会查到后,依然向后遍历 直到不满足条件的
范围查询的话 都是访问到不满足条件的值为止
但是都在内存中,所以性能几乎一致
修改操作的话
唯一索引需要检查唯一性 必须加载到内存中进行判断,直接操作内存
普通索引若数据页在内存中的直接更新
不在的话直接写到changebuffer中也可以
否则就先把更新操作记录到channge buffer 中,等下一次查询将数据读到内存中在进行 channge buffer里相关更新操作后把数据返回,等查询来了才将数据更改操作读到内存中去修改
这样在写多读少的情况下,普通索引减少了磁盘io
aqs (底层是双向链表队列
他存的是节点之间的关联关系,aqs将每条请求共享资源的thread封装成一个clh队列的一个节点来实现锁的分配
1.如果需要在aqs等待队列删除一个线程node节点 方便删除
2.方便唤醒,如果是单向的话有个pre aqs在获取锁时如果获取不到进入等待状态,此时后续节点因为阻塞了无法感知前个node节点的状态,无法唤醒,所以使用双端队列加入了个next属性 方便前个节点释放后主动唤醒后续的节点thread
) tryacquire tryrelease
当共享资源被某个线程占有,其他请求该资源的thread会被阻塞,从而进入一个等待队列
抽象队列同步器 是个父接口 比如reentrantLock semaphore countdownlatch
cyclicbirrer 实现依靠reentrantlock 和 condition实现的
他有个state属性 使用的cas的方式进行修改属性值 aqs主要有两种形式的锁 独占锁和共享锁
如果是独占锁 state=1的时候,然后后边的话在想进入就会进入双端链表的等待队列
他的唤醒和挂起使用的底层为park和unpark的机制进行 锁的
http断点续传
HTTP1.1协议(RFC2616)中定义了断点续传相关的HTTP头 Range和Content-Range字段,一个最简单的断点续传实现大概如下
1. 客户端下载一个1024K的文件,已经下载了其中512K
2. 网络中断,客户端请求续传,因此需要在HTTP头中申明本次需要续传的片段:Range:bytes=512000-,这个头通知服务端从文件的512K位置开始传输文件;
3. 服务端收到断点续传请求,根据请求头的Content-Range来决定从文件流的哪个位置上开始读,比如从文件的512K位置开始传输,并且在HTTP头中增加:Content-Range:bytes 512000-/1024000,并且此时服务端返回的HTTP状态码应该是206,而不是200。
但是在实际场景中,会出现一种情况,即在终端发起续传请求时,URL对应的文件内容在服务端已经发生变化,此时续传的数据肯定是错误的。如何解决这个问题了?
同时定义有一个If-Range头,终端如果在续传是使用If-Range。If-Range中的内容可以为最初收到的ETag头或者是Last-Modfied中的最后修改时候。服务端在收到续传请求时,通过If-Range中的内容进行校验,校验一致时返回206的续传回应,不一致时服务端则返回200回应,回应的内容为新的文件的全部数据。
Mysql主从读写分离
主库写 从库读
1.主库执行sql修改
2.主库成功修改时binlog更新
3.主库的binlog dump线程将更新部分发给从库
4.从库io thread收到binlog更新部分写入relay log中
5.从库读取relay log内容
mysql慢查询优化:
1.查询慢查询查询日志定位sql
2.使用explain进行分析
rabbitmq
RabbitMQ一般用来干嘛?你在项目中怎么用的?消息重复消费怎么办?丢失怎么办?
如何破坏单例 【反射 序列化机制】
都是通过构造器重新创建的
Constructor constructor=Singleton.class.getDeclaredConstructor(null);
constructor.setAccessible(true);
序列化会通过反射调用无参数的构造方法创建一个新的对象。
序列化实现seriallable接口 和 clone 都不会调用构造方法
2.----------------------------------------------------------------------------------------------
1.自己的特点 注意说技术的特点,
自我介绍太啰嗦吧,把技术和项目放在自我介绍会好一点
废话多了好像,应该着重说自己会的东西