一、自我介绍,自己会些什么?
- 处理过高并发问题
- 项目优化经验
- 排查OOM故障
- jvm,mysql,redis底层有着深入的了解
- 项目负责人
- 熟悉项目开发流程
二、什么是并发问题?
- 多个线程同时操作一个公共变量,这个公共变量可以是java中的一个局部变量也可以是mysql中的一条数据,当a,b线程同时将数据加载到自己的工作内存中,a线程对自己工作内存中的数据进行操作修改,将数据更新到了缓存中,然而b线程这是不知道数据已经被更新,b线程也在原来的数据上做出了修改,也更新了回去,这时会把a线程更新的数据覆盖掉,这就是一个并发问题。
三、mysql的优化流程
- 建立一个合适的索引,例如多个字段查询,可以简历一个联合索引,比如你只联合查询二个字段,如果这时你也要联查其他常用的字段,可以将这些字段放入这个联合索引中。
- 代码上,for循环插入数据优化为mysql批量插入,效率值相差百倍
- 添加缓存,减少数据的访问压力
- 定期整理空间碎片,刚开始存储数据在磁盘中是顺序存放的,当频繁对数据库进行增删改时,这时就会产生磁盘碎片,mysql查询效率自然而然就会降低,数据乱序了
- 当mysql数据量上来了,可以考虑主从复制,减少数据库读取的压力,
- 当以上都不能解决问题,这时候需要进行分库分表,减少单表数据量过大问题
四、redis实现分布式锁
- 为什么能用redis做分布式锁,因为redis操作指令的时候是基于单线程的,天然不存在并发问题,最初可用setnx来做分布式锁,加完锁后,如果服务宕机,锁没有释放掉,就需要加入锁的过期时间,让其要不是我们手动给他释放,要么就是自己超时释放。如果这个业务处理时间过长,业务没有来得及处理完,锁就过期了,那么也过存在并发问题,这样的话我们需要引入redission,因为redission里面有一个开门狗机制,会自动帮你轮询查看你的业务有没有处理完,会帮你的锁进行续签,这是redis实现分布式锁的一个演化过程。
五、实际的项目开发流程
- 产品经理对业务整理出原型
- 开会进行原型评审
- 通过后后端进行技术选型
- 通过后各个模块负责进行数据库设计
- 接口定义,交付前端
- 过程中可能出现Ui评审,用例评审,开发完成后,与前端进行联调,自测没问题,将代码部署到测试服务器
- 测试根据业务,正向流程,逆向流程都没问题了,发布到预发布服务器中(本地内测环境)
- 产品,ui进行最后业务需求等方面的测试,验收
- 验收完,代码封板,请示领导提交上线
- 项目完成后进行技术总结,复盘
六、synchorized锁升级的流程是什么?
- 它的锁升级流程是单向的,不会出现降级现象,它的锁有四种状态:无锁,偏向锁,轻量级锁,重量级锁
- 刚刚创建对象时它的锁是属于无锁的一个状态,当线程进入同步代码块时,它会通过CAS操作去给线程中mark word中的那个持有线程id修改成自己的线程id,如果这个CAS修改失败,说明有其他线程持有锁,当前是处于并发情况,这个时候我们会给它升级成轻量级锁,升级之后会继续进行自旋,自旋到规定数量之后,如果还不能获取到锁,这时候会把它升级到重量级锁。
- 偏向锁为什么需要升级为重量级锁?
- 自旋过多会空耗cpu资源的,所以此时线程直接进入内核状态的话会节省cpu资源
- 为什么不直接从偏向锁升级为重量级锁?
- 这个时候线程会直接进入内核态,如果说锁竞争不是很激烈的情况下,它会增加线程上下文的切换,通过自旋可以减少上下文的切换,通过自旋可以马上得到锁的时候,就可以不用进行线程上下文切换,这样可以提高整体的一个效率。
- 重量级锁是怎么实现的?
- 它依赖于一个monitor object对象,就是说当锁升级为重量级锁的时候它会直接关联这个monitor object对象,对象里面有三个核心参数:owner(作用:记录当前锁的线程),waitset(作用:当我们调用线程时,会把线程的节点放入这个waitset方法中),entryList(是一个有序列表,所有线程放在这个里面排队,先进先出,当我们去调用notified()方法的时候,会将waitset里面的一个节点放入entryList的尾部,当我们调用notifyAll()方法时,会将waitset中的所有节点放入到entryList的尾部)。
posted @
2024-04-20 23:10
牛奶配苦瓜
阅读(
5)
评论()
收藏
举报