知识集锦

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
}

bitmap

如图所示,通过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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值