分布式技术问题探讨
一:发现CPU 100%,如何排查?写出排查思路与步骤排查思路:
根据经验首先分析出容易导致CPU飙升到100%的场景都有哪些?包括死循环、频繁的full gc、死锁等情况。排查思路是根据线上日志,找到对应的源码,再结合线程堆栈、堆dump文件等分析出原因。
排查步骤:
1 首先查看CPU占用100%的进程号PID,可以通过TOP等命令查看;
2 通过命令查看对应进程下线程的状态,比如top -H -n 1 -p PID;
3 导出进程的线程文件,比如通过jstack -l PID > ./jstack.log
4 查看jstack.log文件查看线程详情,比如看到代码行数。通过grep tid,其中需注意tid是16进制格式。排查问题是否是由线程死锁等情况导致。
5 同时可以通过jmap工具dump出堆内存快照,分析是否是频繁full gc的原因。在k8s容器环境中可考虑借助arthas等开源工具帮助分析。
二:如何设计一个高可用的架构
首先可以把架构简化成接入层、应用层、数据层3层。而在架构领域针对高可用设计常用的方案有主从复制、分布式一致性、单元化设计等。
1 接入层:包括负载均衡如GSLB、流量网关ngnix、业务网关spring cloud gateway等。可以通过集群化部署来保证高可用,同时通过raft等算法来保证集群的强一致性。
2 应用层:包括注册中心、RPC服务依赖、无状态服务等。其中应用层通过多种技术手段比如幂等设计、无状态设计、熔断降级、异步通知、跨IDC调用等实现服务的高可用。
3 数据层:包括读写分离、Failover库、分库分表、单元化架构等。数据库采用主备模式,通过日志文件保证主从复制。同时增加一个空的Failover库,在主库宕机时,通过业务层框架自动切换到Failover库,从而避免主从切换导致的业务中断等问题。
通过单元化架构解决了跨IDC级别的可用性问题,在IDC中通过用户ID进行分片,每个单元保存独立的流水行数据;针对全局数据,则在各个单元都保存一份,其中不同单元之间可通过消息中间件(数据总线)来完成数据同步,减少时延。
三:如何进行Java性能优化
java程序性能优化从计算、存储、网络3个方面展开;
从计算方面看,常见优化手段包括并发执行、同步转异步、懒加载等。其中并发执行分为多机(例如MapReduce)、多进程(Ngnix)、多线程(Netty)等,并且在资源冲突时通过优化同步机制来提升计算效率,比如读写锁、分段锁、乐观锁、无锁队列等技术。
从存储层面看,常见优化手段包括数据复用、小IO合并、索引优化、分库分表等技术手段。其中数据复用分为本地缓存和分布式缓存redis等形式;数据库写请求可以通过合并小IO请求减少数据库建联次数;通过深入理解innodb等存储引擎底层数据结构,结合联合索引最左匹配原则等增加索引命中率。
从网络层面看,常见优化手段包括多路IO复用、rpc序列化、sidecar性能优化。比如在网关层面采用netty等异步非阻塞的通信框架,底层依赖linux的epoll模型;比如rpc框架采用Protobuf等二进制序列化方式;在k8s中采用eBPF代替iptables提升了数据通信性能。
四:设计解决全局唯一ID问题的技术方案
结合以前的项目实践常用的唯一ID设计方案有类似雪花算法、基于分库分表等方案。
类雪花算法(基于redis)方案:适用于通用的唯一ID使用场景,比如生成日志表ID等各类业务ID。为了便于ID在前端展示,js等语言long类型最长只能52bit,所以设置唯一ID长度为52位,其中16位是基于redis生成的,同时增加instance作为业务区分标识;
基于分库分表的方案:适用于memberid等个性业务场景。比如支付宝2088会员账号唯一ID就有严格的业务规则,比如最后两位01-99用户做单元化的标识。针对这种场景需要在数据库中单独创建一张sequence逻辑表负责生成ID,比如支付宝分库分表规则是100库100表的规则,通过设置合理的初始值和步长解决掉不同表中ID重复的问题。
页:
[1]