技术杂记
程序员文章站
2022-06-13 19:51:17
...
网络编程中 TCP_NODELAY 可以缩短通讯时延。 如果TCP_NODELAY=FALSE, 则打开Nagle 算法,通过延时减少数据包发送数量以解决网络拥堵。
具体的做法就是:
如果发送内容大于等于 1 个 MSS, 立即发送;
如果之前没有包未被 ACK, 立即发送;
如果之前有包未被 ACK, 缓存发送内容;
如果收到 ACK, 立即发送缓存的内容。(MSS 为 TCP 数据包每次能够传输的最大数据分段)
TCP Delayed ACK(延迟确认)就是为了努力改善网络性能,来解决这个问题的,它将几个 ACK 响应组合合在一起成为单个响应,或者将 ACK 响应与响应数据一起发送给对方,从而减少协议开销。
具体的做法是:
当有响应数据要发送时,ACK 会随响应数据立即发送给对方;
如果没有响应数据,ACK 将会延迟发送,以等待看是否有响应数据可以一起发送。在 Linux 系统中,默认这个延迟时间是 40ms;
如果在等待发送 ACK 期间,对方的第二个数据包又到达了,这时要立即发送 ACK。但是如果对方的三个数据包相继到达,第三个数据段到达时是否立即发送 ACK,则取决于以上两条。
当TCP_NODELAY 和 TCP DELAYED ACK 同时生效时,会发生相互等待导致网络延时。
--------------------------------------------------------------------
每个thread有自己的副本threadLocal, threadLocal是存在threadLocalMap中,以threadLocal为key,值为value。 threadLocal的get, set方法可以看作对threadLocalMap的封装。new ThreadLocal<T>() 指定泛型。使用完之后,要使用threadLocal.remove() 方法清理,避免内存泄漏。
--------------------------------------------------------------------
乐观锁的原理基本上是先取值,然后插入的时候有个原子操作(比较值并更新值),如果比较值与原取值不变即成功更新,否则失败。在JAVA里实现CAS,例子AtomicInteger等。
CAS适合资源竞争不大的情况,因为不使用synchronized悲观锁,提升性能,如果资源竞争大,大量线程同时自旋,将影响服务器的正常运转。
--------------------------------------------------------------------
ThreadPoolExecutor 的参数说明与使用
1)corePoolSize 核心线程数
2)maximumPoolSize 最大线程数
3)keepAliveTime 空闲线程存活时间
4)unit 存活时间单位
5)workQueue 等待队列
6)threadFactory 线程工厂
7)handler 拒绝策略
四种情况:
1)任务数小于corePoolSize, 创建线程执行
2)任务数大于corePoolSize, 多余的任务小于workQueue长度, 进入workQueue等待
3)任务数大于corePoolSize, 多余的任务大于workQueue,额外的小于maximumPoolSize-corePoolSize,创建新线程执行
4)任务数大于maximumPoolSize+workQueue,执行handler拒绝策略
--------------------------------------------------------------------
聚集索引是数据和索引在一起,数据的物理顺序和逻辑顺序一致,因此只能有一个聚集索引(但可以包含多列)。非聚集索引是额外建索引表,索引顺序与数据的物理顺序不一致,通常都是这种索引。聚集索引的优点是只需一次查表,缺点是如果索引列频繁变动,造成数据的物理位置变化,影响性能。非聚合索引一般情况下都要查两次表,先查索引,然后查数据。当然如果索引表覆盖了查询的字段,就无需二次查表了。
--------------------------------------------------------------------
信号量限流与线程池限流
线程池上面已经讲过了,使用线程池限流,主要有线程池自动管理完成,超出最大线程数就被拒绝策略拒绝了,达到了限流的目的。信号量限流,主要是靠手动去获取令牌,如果获取到,则开启线程执行,如果未获取到则阻塞,直到有令牌被释放而获取到。两者的方式都应该属于令牌桶限流,还有一种限流方式是漏桶限流,是平滑后端处理的,一般不用到,有兴趣可以自行查阅。
--------------------------------------------------------------------
CAP的理解
C 一致性 A可用性 P分区容错性
单机满足 CP, 做不到高可用
多机情况下必然存在P, 当部分节点故障时,只能在CA之间选择, 选择C,系统持续等待同步,不可用。 选择A, 不能在故障时间内做到一致。
具体的做法就是:
如果发送内容大于等于 1 个 MSS, 立即发送;
如果之前没有包未被 ACK, 立即发送;
如果之前有包未被 ACK, 缓存发送内容;
如果收到 ACK, 立即发送缓存的内容。(MSS 为 TCP 数据包每次能够传输的最大数据分段)
TCP Delayed ACK(延迟确认)就是为了努力改善网络性能,来解决这个问题的,它将几个 ACK 响应组合合在一起成为单个响应,或者将 ACK 响应与响应数据一起发送给对方,从而减少协议开销。
具体的做法是:
当有响应数据要发送时,ACK 会随响应数据立即发送给对方;
如果没有响应数据,ACK 将会延迟发送,以等待看是否有响应数据可以一起发送。在 Linux 系统中,默认这个延迟时间是 40ms;
如果在等待发送 ACK 期间,对方的第二个数据包又到达了,这时要立即发送 ACK。但是如果对方的三个数据包相继到达,第三个数据段到达时是否立即发送 ACK,则取决于以上两条。
当TCP_NODELAY 和 TCP DELAYED ACK 同时生效时,会发生相互等待导致网络延时。
--------------------------------------------------------------------
每个thread有自己的副本threadLocal, threadLocal是存在threadLocalMap中,以threadLocal为key,值为value。 threadLocal的get, set方法可以看作对threadLocalMap的封装。new ThreadLocal<T>() 指定泛型。使用完之后,要使用threadLocal.remove() 方法清理,避免内存泄漏。
--------------------------------------------------------------------
乐观锁的原理基本上是先取值,然后插入的时候有个原子操作(比较值并更新值),如果比较值与原取值不变即成功更新,否则失败。在JAVA里实现CAS,例子AtomicInteger等。
//var1 是this指针 //var2 是地址偏移量 //var4 是自增的数值,是自增1还是自增N public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { //获取内存值,这是内存值已经是旧的,假设我们称作期望值E var5 = this.getIntVolatile(var1, var2); //compareAndSwapInt方法是重点, //var5是期望值,var5 + var4是要更新的值 //这个操作就是调用CAS的JNI,每个线程将自己内存里的内存值M //与var5期望值E作比较,如果相同将内存值M更新为var5 + var4,否则做自旋操作 } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; }
CAS适合资源竞争不大的情况,因为不使用synchronized悲观锁,提升性能,如果资源竞争大,大量线程同时自旋,将影响服务器的正常运转。
--------------------------------------------------------------------
ThreadPoolExecutor 的参数说明与使用
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { }
1)corePoolSize 核心线程数
2)maximumPoolSize 最大线程数
3)keepAliveTime 空闲线程存活时间
4)unit 存活时间单位
5)workQueue 等待队列
6)threadFactory 线程工厂
7)handler 拒绝策略
ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 60L, TimeUnit.SECONDS,new LinkedBlockingQueue<>(1));
四种情况:
1)任务数小于corePoolSize, 创建线程执行
2)任务数大于corePoolSize, 多余的任务小于workQueue长度, 进入workQueue等待
3)任务数大于corePoolSize, 多余的任务大于workQueue,额外的小于maximumPoolSize-corePoolSize,创建新线程执行
4)任务数大于maximumPoolSize+workQueue,执行handler拒绝策略
--------------------------------------------------------------------
聚集索引是数据和索引在一起,数据的物理顺序和逻辑顺序一致,因此只能有一个聚集索引(但可以包含多列)。非聚集索引是额外建索引表,索引顺序与数据的物理顺序不一致,通常都是这种索引。聚集索引的优点是只需一次查表,缺点是如果索引列频繁变动,造成数据的物理位置变化,影响性能。非聚合索引一般情况下都要查两次表,先查索引,然后查数据。当然如果索引表覆盖了查询的字段,就无需二次查表了。
--------------------------------------------------------------------
信号量限流与线程池限流
线程池上面已经讲过了,使用线程池限流,主要有线程池自动管理完成,超出最大线程数就被拒绝策略拒绝了,达到了限流的目的。信号量限流,主要是靠手动去获取令牌,如果获取到,则开启线程执行,如果未获取到则阻塞,直到有令牌被释放而获取到。两者的方式都应该属于令牌桶限流,还有一种限流方式是漏桶限流,是平滑后端处理的,一般不用到,有兴趣可以自行查阅。
--------------------------------------------------------------------
CAP的理解
C 一致性 A可用性 P分区容错性
单机满足 CP, 做不到高可用
多机情况下必然存在P, 当部分节点故障时,只能在CA之间选择, 选择C,系统持续等待同步,不可用。 选择A, 不能在故障时间内做到一致。
上一篇: 技术杂记
下一篇: 为了权妃的死,朱棣株连宫女3000多人