常见问题整理

性能相关

服务器cpu过高

怎么定位和查看:

  1. top命令 看cpu占用高的进程 , ps 找到cpu高的线程 然后定位代码
  2. 查看相关日志

内存过高

查看:
free -m 查看服务器内存使用情况,-m的意思是内存显示单位是mb
top 查看服务器所有进程占用内存,为了查看方便,可以使用
日志

原因:
1.内存泄漏
2.缓存使用不当
3.

内存泄漏如何定位和处理

可能发生内存泄漏的场景

  1. 申请过多的goroutine 例如在for循环中申请过多的goroutine来不及释放导致内存泄漏
  2. 协程结束时协程中的channel没有关闭,导致一直阻塞;例如协程中有死循环
  3. 切片截取引起子切片内存泄漏 解决 : append

排查内存泄漏 :pprof 分析工具
pprof 支持四种类型的分析:
CPU分析
Memory内存分析
Block阻塞分析,
Mutex互斥锁分析

golang相关

map 是并发安全的吗 为啥

1.不是 :golang map 没有做并发控制 ,加锁或使用其他同步机制会增加复杂性和开销
如何实现并发安全的 map
1.加锁 : 对整个map加上读写锁sync.RWMutex
2.sync.map
sync.Map思想:就是用两个数据结构(只读的 read 和可写的 dirty)尽量将读写操作分开,来减少锁对性能的影响

golang GC 时机

Go语言中有三种GC的触发时机:

系统的定时触发:如果两分钟内没有触发GC,则会每隔两分钟进行触发一次GC。(gcTriggerTime)
用户显示调用:用户调用runtime.GC方法,进行强制触发
申请内存时触发:给对象申请堆空间的时候,可能会触发GC,调用mallocgc的方法 (gcTriggerHeap)

MySql

Redis

kafka

kafka高吞吐的原因

Zero Copy(零拷贝)技术
Page Cache(页缓存)+磁盘顺序写
分区分段+索引
批量读写
批量压缩

kafka 和redis list 的区别

kafka优点:
消息持久化 :redis是内存数据库,虽然有aof和rdb两种机制进行持久化,但这只是辅助手段,这两种手段都是不可靠的。
热key性能问题 。如果对某个list的并发读写非常高,就产生了无法解决的热key
没有确认机制 :每当执行rpop消费一条数据,那条消息就被从list中永久删除了。
不支持多订阅者 :一条消息只能被一个消费者消费,rpop之后就没了。
不支持二次消费 :一条消息rpop之后就没了。

kafka重复消费和消息丢失

重复消费

.1 Consumer消费过程中,进程挂掉/异常退出,offset未提交 读到之前的offset

位移(Offset)的提交有两种方式,自动提交和手动提交。
解决 :精确一次性消费
消费数据和提交offset 绑定做原子操作 可利用redis 活mysql的事务
将唯一标识存入Redis,要操作数据的时候先判断缓存有没有这个唯一标识。
将版本号(offset)存入到数据里面,然后再要操作数据的时候用这个版本号做乐观锁,当版本号大于原先的才能操作。

.2 消费者消费时间过长
Kafka消费端的参数max.poll.interval.ms定义了两次poll的最大间隔,它的默认值是 5 分钟, Consumer 如果在 5 分钟之内无法消费完 poll方法返回的消息,那么Consumer 会主动发起“离开组”的请求。

解决 : 根据情况调整 max.poll.interval.ms 值
提高单条消息的处理速度:异步的、多线程处理等

消息丢失

1**.生产者端丢失**

Replica ACK :
0 :表示生产者将数据发送出去不等待任何返回,效率最高,可靠性最低
1:(默认级别):表示数据发送到Kafka 后,经过leader确认收到消息,才算发送成功,如果leader宕机了,就会丢失数据。
-1(all): 表示生产者需要等待ISR中的所有follower同步完数据后才算发送完成,这样数据不会丢失,因此可靠性最高,性能最低。

解决方案:
1 通过设置RequiredAcks模式来解决,选用WaitForAll(对应值为-1)可以保证数据推送成功,不过会影响延时。
2 引入重试机制,设置重试次数和重试间隔。
3 当然,最后就是使用Kafka的多副本机制保证Kafka集群本身的可靠性,确保当Leader挂掉之后能进行Follower选举晋升为新的Leader。

2 消费者丢失
消费端的消息丢失主要是因为在消费过程中出现了异常,但是对应消息的 Offset 已经提交,那么消费异常的消息将会丢失。
解决 :手动提交offset

tcp为啥是三次握手,四次挥手

三次握手才可以阻止重复历史连接的初始化 (客户端收到后可以根据自身的上下文,判断这是一个历史连接)
三次握手才可以同步双方的初始序列号

四次挥手:被动方 回复ACK后,要处理现有的请求完成后,才能发第三次挥手 FIN

你可能感兴趣的:(开发语言)