前言
二面已过,等HR面小公司,Redis写AOF文件时采用的写时复制,力扣就刷了一道题(太难了)。
1.二面面经
全是场景题
栈和队列的特性,你遇到过压栈吗(拿捏)
这个太简单了 略过了
统计文件夹文件的个数(递归) 说递归然后 递归放代码中间和放代码最后的区别 (拿捏)
递归函数放中间可以回溯嘛
3个服务器都有用户数据 如何合并到一起(id有重复)(拿捏)
个人回答,在用户id的基础上可以加上服务器的地址作为唯一索引就可以防止重复了 这个方法还是毕竟好的个人感觉
多端登录和踢人下线如何实现 (拿捏)
多端登录你不拦截就行了,踢人下线把Redis里面的token数据清空掉那么另一端再次请求时检验一下token就可以了
签到功能(有15天的 30天的自己定义)如何用mysql实现一行纪录能不能实现 (拿捏)
可以采用01010101这样来存储,位图这种数据结构
OOM异常如何排查 内存泄露大概率一般发生哪里 拿捏
拉取线上的dump文件 分析哪个对象太多,查看GC日志看看是否发送fullGC还是无法清理。内存泄露一般都在ThreadLocal里面,这里就不详解了看源码就知道了简单很。
登录功能用户名密码如何存储 (拿捏)
加密后存嘛,前端是HTTPS那么明文就行了是安全的不会拦截到你的
分库分表一般的实现,你知道如何通过线上来选用哪个方案 (拿捏)
分库分表,最重要的是分布式id可以采用雪花算法实现,mycat和sharding 都是不错的分库分表工具,我自己是手写了一套分库分表工具。
2. Redis持久化机制
大家都知道Redis是一个基于内存的非关系数据库,它也是有持久化机制的。
1.RDB 全量备份
为什么叫做全量备份呢,当触发持久化机制的时候他默认会把当前内存的数据全部以二进制的形式弄到磁盘上。
优点:显而易见,数据恢复快,磁盘容量小 缺点:持久化数据太慢,每次都是全量备份。实时性差,我们不可能配置一秒一次RDB备份吧,太消耗资源了。
关于fork()出子进程去备份RDB文件Redis采用一个叫做写时复制技术,他在写RDB文件时不会阻塞读操作,他不是操作原来的资源,他会弄一个备份来操作然后在把他覆盖过去。
2. AOF 增量备份
增量复制嘛,听名字就知道一半了,写命令的时候都是在文件尾部插入一条语句。这样的话是不是就很快了啊。
当然不会每一条set语句都去写,这样的话IO操作太多了就太耗性能了,Redis弄了一个缓存区来存放需要set命令会根据配置来持久化写磁盘,这样就会很快了,虽然可能会丢失一些数据,但是解决了速度问题。AOF也不是没缺点的。
优点:持久化速度快。缺点:磁盘消耗大,速度恢复速度慢。
AOF Redis做了很多优化,重写日志,比如set a 1,set a = 100那么他就会优化为一条命令set a 100减少了操作和磁盘大小。
3. 混合双打持久化机制
定期把持久化文件会把当前的文件转化为二进制,后面的就是命令行了,010101010101后面来一个 set a 100这种,这样的话就折中了,Redis还是很好的,他什么都用折中方案哈哈。如惰性删除和定期删除也是折中的。
3. java写时复制集合
CopyOnWriteArrayList
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();//拿到当前数组
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);//复制一个多1个容量
newElements[len] = e;//赋值
setArray(newElements);//刷新回去
return true;
} finally {
lock.unlock();
}
}
java的写时复制List还是非常简单的。