Kafka专题:1.kafka高性能的原因
高性能包含两个方向
写的高性能
1)顺序写+page cache
2)生产者批量发送消息集,压缩:生产者并不直接将消息发送给服务端,先在客户端把消息放入队列中,然后由一个消息发送线程从队列中拉取消息,以批量的方式发送给服务端。同一个节点上面的不同分区消息会一个批次发送,减少网络发送次数。kafka使用selector处理网络连接与读写处理。
读的高性能
1)顺序读+Zero copy
2)消费者批量拉取(可以指定大小)
开发者提升性能的手段
1)增加partition+增加消费者实例
什么时候为提交成功呢?
所有的ISR节点都写入成功,才算提交成功(注意,isr节点不是所有副本节点,是所有节点的一个子集,在PartitionInfo类中,包含两个属性 Node[] replicas 分区所有副本;另一个是Node[] inSyncReplicas 也就是ISR节点列表,当一个副本落后主副本太多,就会从isr列表中移除,避免影响消息的commit)
有序性如何保证?
同一分区内消息有序,不同的分区,消息无序。(对需要保证消费顺序的消息放到同一分区即可)
消息是如何负载均衡到某一个分区的呢?
1)round robin 随机轮询(消息没有key)
2)对key进行散列化,对分区数量取模得到分区编号
3)消息在生产者客户端就已经确定好了partition的id,每一个partition有一个双端队列来缓存客户端的消息,队列满了才进行一次向服务器的发送。发送的时候,是以节点为单位的,比如一个节点上有10个分区,这10个分区的消息,是一次网络请求进行发送的。
客户端网络连接对象NetworkClient管理了客户端与服务端之间的网络通信,包括连接的建立,发送客户端请求,读取客户端响应。
包含三个方法
1)ready (),服务端是否准备好,如果准备好,调用Selector.connect()方法建立连接
2)send(),将客户端请求加入inFlightRequests列表,然后调用Selector.send()方法,这一步只是将请求暂存到节点对应的网络通道中,还没有真正的发送出去。
针对同一个服务端,如果上一个客户端请求还没有发送完成,则不允许发送新的客户端请求。InFlightRequests类包含一个节 点到双端队列的映射结构。 在准备发送客户端请求时,请求将添加到指定节点对应的队列中;在收到 响应后 ,才会将请求从队列中移 除 。
3)poll(),真正的发送,调用Selector.poll方法
常见的题
N阶楼梯问题(动态规划)
https://blog.youkuaiyun.com/xiao_chen_l/article/details/81174900
查找数组中第k大的数
问题: 查找出一给定数组中第k大的数。例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8……
思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]。
https://www.cnblogs.com/wsw-seu/p/7652495.html
go快排
1.选取基准值tag:选取第一个元素为基准值(每次递归调用的基准值不等)
2.从0向后查找到比tag大的数,否则i++
3.从n向前查找到比tag小的数,否则j–
4.交换两个数
5.全部交换后此时i==j,递归调用,继续比较i位置两侧位置
//第一种方式,递归传入分割后的数组
func quicksort(s []int){
if len(s)<=0 {
return
}
tag:=s[0]
i:=0
j:=len(s)-1
for i<j {
for s[j]>tag&&i<j {
j--
}
for s[i]<tag&&i<j {
i++
}
s[i],s[j]=s[j],s[i]//交换
}
quicksort(s[:i])
quicksort(s[i+1:])
}
//第二种方式,递归传入原数组
func quicksort(s []int,start int,end int){
if start >=end{
return
}
tag:=s[start]
i:=start
j:=end
for i<j {
for s[j]>tag&&i<j {
j--
}
for s[i]<tag&&i<j {
i++
}
s[i],s[j]=s[j],s[i]//交换
}
quicksort(s,start,i-1)
quicksort(s,i+1,end)
}
数据结构
二叉树的销毁
https://www.cnblogs.com/Romi/archive/2012/08/30/2664575.html
####如何判断单链表是否有环,如果有怎么找到进入环的节点
https://blog.youkuaiyun.com/weixin_30840573/article/details/95642135
Go语言——垃圾回收GC
Go语言——垃圾回收GC
参考:
Go 垃圾回收原理
Golang源码探索(三) GC的实现原理
Getting to Go: The Journey of Go’s Garbage Collector
Go的三色标记GC
引用计数:对每个对象维护一个引用计数,当引用该对象的对象被销毁时,引用计数减1,当引用计数器为0是回收该对象。
优点:对象可以很快的被回收,不会出现内存耗尽或达到某个阀值时才回收。
缺点:不能很好的处理循环引用,而且实时维护引用计数,有也一定的代价。
代表语言:Python、PHP、Swift
标记-清除:从根变量开始遍历所有引用的对象,引用的对象标记为"被引用",没有被标记的进行回收。
优点:解决了引用计数的缺点。
缺点:需要STW,即要暂时停掉程序运行。
代表语言:Golang(其采用三色标记法)
分代收集:按照对象生命周期长短划分不同的代空间,生命周期长的放入老年代,而短的放入新生代,不同代有不能的回收算法和回收频率。
优点:回收性能好
缺点:算法复杂
代表语言: JAVA
root
首先标记root根对象,根对象的子对象也是存活的。
根对象包括:全局变量,各个G stack上的变量等。
标记
在之前的Go语言——内存管理一文中,分析过span是内存管理的最小单位,所以猜测gc的粒度也是span。
type mspan struct {
// allocBits and gcmarkBits hold pointers to a span's mark and
// allocation bits. The pointers are 8 byte aligned.
// There are three arenas where this data is held.
// free: Dirty arenas that are no longer accessed
// and can be reused.
// next: Holds information to be used in the next GC cycle.
// current: Information being used during this GC cycle.
// previous: Information being used during the last GC cycle.
// A new GC cycle starts with the call to finishsweep_m.
// finishsweep_m moves the previous arena to the free arena,
// the current arena to the previous arena, and
// the next arena to the current arena.
// The next arena is populated as the spans request
// memory to hold gcmarkBits for the next GC cycle as well
// as allocBits for newly allocated spans.
//
// The pointer arithmetic is done "by hand" instead of using
// arrays to avoid bounds checks along critical performance
// paths.
// The sweep will free the old allocBits and set allocBits to the
// gcmarkBits. The gcmarkBits are replaced with a fresh zeroed
// out memory.
allocBits *gcBits
gcmarkBits *gcBits
}
如图所示,通过gcmarkBits位图标记span的块是否被引用。对应内存分配中的bitmap区。
三色标记
灰色:对象已被标记,但这个对象包含的子对象未标记
黑色:对象已被标记,且这个对象包含的子对象也已标记,gcmarkBits对应的位为1(该对象不会在本次GC中被清理)
白色:对象未被标记,gcmarkBits对应的位为0(该对象将会在本次GC中被清理)
例如,当前内存中有A~F一共6个对象,根对象a,b本身为栈上分配的局部变量,根对象a、b分别引用了对象A、B, 而B对象又引用了对象D,则GC开始前各对象的状态如下图所示:
初始状态下所有对象都是白色的。
接着开始扫描根对象a、b; 由于根对象引用了对象A、B,那么A、B变为灰色对象,接下来就开始分析灰色对象,分析A时,A没有引用其他对象很快就转入黑色,B引用了D,则B转入黑色的同时还需要将D转为灰色,进行接下来的分析。
灰色对象只有D,由于D没有引用其他对象,所以D转入黑色。标记过程结束
最终,黑色的对象会被保留下来,白色对象会被回收掉。
STW
stop the world是gc的最大性能问题,对于gc而言,需要停止所有的内存变化,即停止所有的goroutine,等待gc结束之后才恢复。
触发
阈值:默认内存扩大一倍,启动gc
定期:默认2min触发一次gc,src/runtime/proc.go:forcegcperiod
手动:runtime.gc()
go gc
go gc
GO的GC是并行GC, 也就是GC的大部分处理和普通的go代码是同时运行的, 这让GO的GC流程比较复杂.
Stack scan:Collect pointers from globals and goroutine stacks。收集根对象(全局变量,和G stack),开启写屏障。全局变量、开启写屏障需要STW,G stack只需要停止该G就好,时间比较少。
Mark: Mark objects and follow pointers。标记所有根对象, 和根对象可以到达的所有对象不被回收。
Mark Termination: Rescan globals/changed stack, finish mark。重新扫描全局变量,和上一轮改变的stack(写屏障),完成标记工作。这个过程需要STW。
Sweep: 按标记结果清扫span
目前整个GC流程会进行两次STW(Stop The World), 第一次是Stack scan阶段, 第二次是Mark Termination阶段.
第一次STW会准备根对象的扫描, 启动写屏障(Write Barrier)和辅助GC(mutator assist).
第二次STW会重新扫描部分根对象, 禁用写屏障(Write Barrier)和辅助GC(mutator assist).
从1.8以后的golang将第一步的stop the world 也取消了,这又是一次优化; 1.9开始, 写屏障的实现使用了Hybrid Write Barrier, 大幅减少了第二次STW的时间.
写屏障
因为go支持并行GC, GC的扫描和go代码可以同时运行, 这样带来的问题是GC扫描的过程中go代码有可能改变了对象的依赖树。
例如开始扫描时发现根对象A和B, B拥有C的指针。
GC先扫描A,A放入黑色
B把C的指针交给A
GC再扫描B,B放入黑色
C在白色,会回收;但是A其实引用了C。
为了避免这个问题, go在GC的标记阶段会启用写屏障(Write Barrier).
启用了写屏障(Write Barrier)后,在GC第三轮rescan阶段,根据写屏障标记将C放入灰色,防止C丢失。
作者:陈先生_9e91
链接:https://www.jianshu.com/p/8b0c0f7772da
Mysql
MySQL 性能调优的10个方法
https://www.cnblogs.com/chenshengqun/p/8875512.html
mysql各种锁介绍
https://blog.youkuaiyun.com/mikewuhao/article/details/99304495
事务的隔离级别
https://blog.youkuaiyun.com/zhouym_/article/details/90381606
数据库SQL语句性能分析
https://blog.youkuaiyun.com/qq_37465368/article/details/82938878
SQL语句性能分析
https://www.cnblogs.com/jingzaixin/p/11424066.html
mysql数据库索引类型和原理
https://www.cnblogs.com/owenma/p/8575646.html
数据库索引原理,及MySQL索引使用
https://blog.youkuaiyun.com/weixin_42181824/article/details/82261988
Mongo
MongoDB实战性能优化
https://www.cnblogs.com/swordfall/p/10427150.html
mongodb性能优化
https://www.cnblogs.com/ngy0217/p/11080787.html
ETCD
彻底搞懂etcd raft选举、数据同步
https://www.cnblogs.com/sunsky303/p/11451755.html
RESTful API 设计指南 - 阮一峰的网络日志
http://www.ruanyifeng.com/blog/2014/05/restful_api.html
Redis
Redis的五大数据类型的底层实现
https://www.cnblogs.com/MouseDong/p/11134039.html
Golang 的引用类型底层实现 - 知乎
https://zhuanlan.zhihu.com/p/111796041