高并发场景下,6种解决SimpleDateFormat类的线程安全问题方法

并发,场景,解决,simpledateformat,线程,安全,问题,方法 · 浏览次数 : 118

小编点评

**SimpleDateFormat测试** ```java package io.binghe.concurrent.lab06; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class SimpleDateFormatTest08 { //执行总次数 private static final int EXECUTE_COUNT = 1000; //同时运行的线程数量 private static final int THREAD_COUNT = 20; private static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd"); public static void main(String[] args) throws InterruptedException { // Semaphore用于线程同步 final Semaphore semaphore = new Semaphore(THREAD_COUNT); // CountDownLatch用于线程同步 final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT); // 创建ExecutorService并启动线程 ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < EXECUTE_COUNT; i++){ executorService.execute(() -> { try { // 获取Semaphore锁,保证线程同步 semaphore.acquire(); // 使用DateTimeFormatter格式化日期和时间 DateTime dateTime = dateTimeFormatter.parse("2020-01-01"); // 打印格式化后的日期和时间 System.out.println(dateTime.toString()); } catch (Exception e){ // 打印格式化失败的日期和时间 System.out.println("格式化日期和时间失败"); } finally { //释放Semaphore锁 semaphore.release(); } }); }); //计数 downLatch,等待线程完成格式化操作 countDownLatch.countDown(); //关闭ExecutorService executorService.shutdown(); //打印所有线程格式化日期成功 System.out.println("所有线程格式化日期成功"); } } ``` **结论** SimpleDateFormat测试是线程安全问题的解决方案,使用joda-time库可以解决线程安全问题,提高性能。

正文

摘要:解决SimpleDateFormat类在高并发场景下的线程安全问题可以有多种方式,这里,就列举几个常用的方式供参考。

本文分享自华为云社区《【高并发】更正SimpleDateFormat类线程不安全问题分析的错误》,作者: 冰 河 。

解决SimpleDateFormat类在高并发场景下的线程安全问题可以有多种方式,这里,就列举几个常用的方式供参考,大家也可以在评论区给出更多的解决方案。

1.局部变量法

最简单的一种方式就是将SimpleDateFormat类对象定义成局部变量,如下所示的代码,将SimpleDateFormat类对象定义在parse(String)方法的上面,即可解决问题。

package io.binghe.concurrent.lab06;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
 * @author binghe
 * @version 1.0.0
 * @description 局部变量法解决SimpleDateFormat类的线程安全问题
 */
public class SimpleDateFormatTest02 {
 //执行总次数
 private static final int EXECUTE_COUNT = 1000;
 //同时运行的线程数量
 private static final int THREAD_COUNT = 20;
 public static void main(String[] args) throws InterruptedException {
 final Semaphore semaphore = new Semaphore(THREAD_COUNT);
 final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
 ExecutorService executorService = Executors.newCachedThreadPool();
 for (int i = 0; i < EXECUTE_COUNT; i++){
 executorService.execute(() -> {
 try {
 semaphore.acquire();
 try {
 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
 simpleDateFormat.parse("2020-01-01");
 } catch (ParseException e) {
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }catch (NumberFormatException e){
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }
 semaphore.release();
 } catch (InterruptedException e) {
 System.out.println("信号量发生错误");
 e.printStackTrace();
 System.exit(1);
 }
 countDownLatch.countDown();
 });
 }
 countDownLatch.await();
 executorService.shutdown();
 System.out.println("所有线程格式化日期成功");
 }
}

此时运行修改后的程序,输出结果如下所示。

所有线程格式化日期成功

至于在高并发场景下使用局部变量为何能解决线程的安全问题,会在【JVM专题】的JVM内存模式相关内容中深入剖析,这里不做过多的介绍了。

当然,这种方式在高并发下会创建大量的SimpleDateFormat类对象,影响程序的性能,所以,这种方式在实际生产环境不太被推荐。

2.synchronized锁方式

将SimpleDateFormat类对象定义成全局静态变量,此时所有线程共享SimpleDateFormat类对象,此时在调用格式化时间的方法时,对SimpleDateFormat对象进行同步即可,代码如下所示。

package io.binghe.concurrent.lab06;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
 * @author binghe
 * @version 1.0.0
 * @description 通过Synchronized锁解决SimpleDateFormat类的线程安全问题
 */
public class SimpleDateFormatTest03 {
 //执行总次数
 private static final int EXECUTE_COUNT = 1000;
 //同时运行的线程数量
 private static final int THREAD_COUNT = 20;
 //SimpleDateFormat对象
 private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
 public static void main(String[] args) throws InterruptedException {
 final Semaphore semaphore = new Semaphore(THREAD_COUNT);
 final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
 ExecutorService executorService = Executors.newCachedThreadPool();
 for (int i = 0; i < EXECUTE_COUNT; i++){
 executorService.execute(() -> {
 try {
 semaphore.acquire();
 try {
 synchronized (simpleDateFormat){
 simpleDateFormat.parse("2020-01-01");
 }
 } catch (ParseException e) {
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }catch (NumberFormatException e){
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }
 semaphore.release();
 } catch (InterruptedException e) {
 System.out.println("信号量发生错误");
 e.printStackTrace();
 System.exit(1);
 }
 countDownLatch.countDown();
 });
 }
 countDownLatch.await();
 executorService.shutdown();
 System.out.println("所有线程格式化日期成功");
 }
}

此时,解决问题的关键代码如下所示。

synchronized (simpleDateFormat){
simpleDateFormat.parse("2020-01-01");
}

运行程序,输出结果如下所示。

所有线程格式化日期成功

需要注意的是,虽然这种方式能够解决SimpleDateFormat类的线程安全问题,但是由于在程序的执行过程中,为SimpleDateFormat类对象加上了synchronized锁,导致同一时刻只能有一个线程执行parse(String)方法。此时,会影响程序的执行性能,在要求高并发的生产环境下,此种方式也是不太推荐使用的。

3.Lock锁方式

Lock锁方式与synchronized锁方式实现原理相同,都是在高并发下通过JVM的锁机制来保证程序的线程安全。通过Lock锁方式解决问题的代码如下所示。

package io.binghe.concurrent.lab06;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * @author binghe
 * @version 1.0.0
 * @description 通过Lock锁解决SimpleDateFormat类的线程安全问题
 */
public class SimpleDateFormatTest04 {
 //执行总次数
 private static final int EXECUTE_COUNT = 1000;
 //同时运行的线程数量
 private static final int THREAD_COUNT = 20;
 //SimpleDateFormat对象
 private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
 //Lock对象
 private static Lock lock = new ReentrantLock();
 public static void main(String[] args) throws InterruptedException {
 final Semaphore semaphore = new Semaphore(THREAD_COUNT);
 final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
 ExecutorService executorService = Executors.newCachedThreadPool();
 for (int i = 0; i < EXECUTE_COUNT; i++){
 executorService.execute(() -> {
 try {
 semaphore.acquire();
 try {
 lock.lock();
 simpleDateFormat.parse("2020-01-01");
 } catch (ParseException e) {
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }catch (NumberFormatException e){
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }finally {
 lock.unlock();
 }
 semaphore.release();
 } catch (InterruptedException e) {
 System.out.println("信号量发生错误");
 e.printStackTrace();
 System.exit(1);
 }
 countDownLatch.countDown();
 });
 }
 countDownLatch.await();
 executorService.shutdown();
 System.out.println("所有线程格式化日期成功");
 }
}

通过代码可以得知,首先,定义了一个Lock类型的全局静态变量作为加锁和释放锁的句柄。然后在simpleDateFormat.parse(String)代码之前通过lock.lock()加锁。这里需要注意的一点是:为防止程序抛出异常而导致锁不能被释放,一定要将释放锁的操作放到finally代码块中,如下所示。

finally {
lock.unlock();
}

运行程序,输出结果如下所示。

所有线程格式化日期成功

此种方式同样会影响高并发场景下的性能,不太建议在高并发的生产环境使用。

4.ThreadLocal方式

使用ThreadLocal存储每个线程拥有的SimpleDateFormat对象的副本,能够有效的避免多线程造成的线程安全问题,使用ThreadLocal解决线程安全问题的代码如下所示。

package io.binghe.concurrent.lab06;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
 * @author binghe
 * @version 1.0.0
 * @description 通过ThreadLocal解决SimpleDateFormat类的线程安全问题
 */
public class SimpleDateFormatTest05 {
 //执行总次数
 private static final int EXECUTE_COUNT = 1000;
 //同时运行的线程数量
 private static final int THREAD_COUNT = 20;
 private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
 @Override
 protected DateFormat initialValue() {
 return new SimpleDateFormat("yyyy-MM-dd");
 }
 };
 public static void main(String[] args) throws InterruptedException {
 final Semaphore semaphore = new Semaphore(THREAD_COUNT);
 final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
 ExecutorService executorService = Executors.newCachedThreadPool();
 for (int i = 0; i < EXECUTE_COUNT; i++){
 executorService.execute(() -> {
 try {
 semaphore.acquire();
 try {
 threadLocal.get().parse("2020-01-01");
 } catch (ParseException e) {
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }catch (NumberFormatException e){
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }
 semaphore.release();
 } catch (InterruptedException e) {
 System.out.println("信号量发生错误");
 e.printStackTrace();
 System.exit(1);
 }
 countDownLatch.countDown();
 });
 }
 countDownLatch.await();
 executorService.shutdown();
 System.out.println("所有线程格式化日期成功");
 }
}

通过代码可以得知,将每个线程使用的SimpleDateFormat副本保存在ThreadLocal中,各个线程在使用时互不干扰,从而解决了线程安全问题。

运行程序,输出结果如下所示。

所有线程格式化日期成功

此种方式运行效率比较高,推荐在高并发业务场景的生产环境使用。

另外,使用ThreadLocal也可以写成如下形式的代码,效果是一样的。

package io.binghe.concurrent.lab06;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
 * @author binghe
 * @version 1.0.0
 * @description 通过ThreadLocal解决SimpleDateFormat类的线程安全问题
 */
public class SimpleDateFormatTest06 {
 //执行总次数
 private static final int EXECUTE_COUNT = 1000;
 //同时运行的线程数量
 private static final int THREAD_COUNT = 20;
 private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();
 private static DateFormat getDateFormat(){
 DateFormat dateFormat = threadLocal.get();
 if(dateFormat == null){
 dateFormat = new SimpleDateFormat("yyyy-MM-dd");
 threadLocal.set(dateFormat);
 }
 return dateFormat;
 }
 public static void main(String[] args) throws InterruptedException {
 final Semaphore semaphore = new Semaphore(THREAD_COUNT);
 final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
 ExecutorService executorService = Executors.newCachedThreadPool();
 for (int i = 0; i < EXECUTE_COUNT; i++){
 executorService.execute(() -> {
 try {
 semaphore.acquire();
 try {
 getDateFormat().parse("2020-01-01");
 } catch (ParseException e) {
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }catch (NumberFormatException e){
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }
 semaphore.release();
 } catch (InterruptedException e) {
 System.out.println("信号量发生错误");
 e.printStackTrace();
 System.exit(1);
 }
 countDownLatch.countDown();
 });
 }
 countDownLatch.await();
 executorService.shutdown();
 System.out.println("所有线程格式化日期成功");
 }
}

5.DateTimeFormatter方式

DateTimeFormatter是Java8提供的新的日期时间API中的类,DateTimeFormatter类是线程安全的,可以在高并发场景下直接使用DateTimeFormatter类来处理日期的格式化操作。代码如下所示。

package io.binghe.concurrent.lab06;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
 * @author binghe
 * @version 1.0.0
 * @description 通过DateTimeFormatter类解决线程安全问题
 */
public class SimpleDateFormatTest07 {
 //执行总次数
 private static final int EXECUTE_COUNT = 1000;
 //同时运行的线程数量
 private static final int THREAD_COUNT = 20;
 private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
 public static void main(String[] args) throws InterruptedException {
 final Semaphore semaphore = new Semaphore(THREAD_COUNT);
 final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
 ExecutorService executorService = Executors.newCachedThreadPool();
 for (int i = 0; i < EXECUTE_COUNT; i++){
 executorService.execute(() -> {
 try {
 semaphore.acquire();
 try {
 LocalDate.parse("2020-01-01", formatter);
 }catch (Exception e){
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }
 semaphore.release();
 } catch (InterruptedException e) {
 System.out.println("信号量发生错误");
 e.printStackTrace();
 System.exit(1);
 }
 countDownLatch.countDown();
 });
 }
 countDownLatch.await();
 executorService.shutdown();
 System.out.println("所有线程格式化日期成功");
 }
}

可以看到,DateTimeFormatter类是线程安全的,可以在高并发场景下直接使用DateTimeFormatter类来处理日期的格式化操作。

运行程序,输出结果如下所示。

所有线程格式化日期成功

使用DateTimeFormatter类来处理日期的格式化操作运行效率比较高,推荐在高并发业务场景的生产环境使用。

6.joda-time方式

joda-time是第三方处理日期时间格式化的类库,是线程安全的。如果使用joda-time来处理日期和时间的格式化,则需要引入第三方类库。这里,以Maven为例,如下所示引入joda-time库。

<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>

引入joda-time库后,实现的程序代码如下所示。

package io.binghe.concurrent.lab06;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
 * @author binghe
 * @version 1.0.0
 * @description 通过DateTimeFormatter类解决线程安全问题
 */
public class SimpleDateFormatTest08 {
 //执行总次数
 private static final int EXECUTE_COUNT = 1000;
 //同时运行的线程数量
 private static final int THREAD_COUNT = 20;
 private static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd");
 public static void main(String[] args) throws InterruptedException {
 final Semaphore semaphore = new Semaphore(THREAD_COUNT);
 final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
 ExecutorService executorService = Executors.newCachedThreadPool();
 for (int i = 0; i < EXECUTE_COUNT; i++){
 executorService.execute(() -> {
 try {
 semaphore.acquire();
 try {
 DateTime.parse("2020-01-01", dateTimeFormatter).toDate();
 }catch (Exception e){
 System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失败");
 e.printStackTrace();
 System.exit(1);
 }
 semaphore.release();
 } catch (InterruptedException e) {
 System.out.println("信号量发生错误");
 e.printStackTrace();
 System.exit(1);
 }
 countDownLatch.countDown();
 });
 }
 countDownLatch.await();
 executorService.shutdown();
 System.out.println("所有线程格式化日期成功");
 }
}

这里,需要注意的是:DateTime类是org.joda.time包下的类,DateTimeFormat类和DateTimeFormatter类都是org.joda.time.format包下的类,如下所示。

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

运行程序,输出结果如下所示。

所有线程格式化日期成功

使用joda-time库来处理日期的格式化操作运行效率比较高,推荐在高并发业务场景的生产环境使用。

解决SimpleDateFormat类的线程安全问题的方案总结

综上所示:在解决解决SimpleDateFormat类的线程安全问题的几种方案中,局部变量法由于线程每次执行格式化时间时,都会创建SimpleDateFormat类的对象,这会导致创建大量的SimpleDateFormat对象,浪费运行空间和消耗服务器的性能,因为JVM创建和销毁对象是要耗费性能的。所以,不推荐在高并发要求的生产环境使用。

synchronized锁方式和Lock锁方式在处理问题的本质上是一致的,通过加锁的方式,使同一时刻只能有一个线程执行格式化日期和时间的操作。这种方式虽然减少了SimpleDateFormat对象的创建,但是由于同步锁的存在,导致性能下降,所以,不推荐在高并发要求的生产环境使用。

ThreadLocal通过保存各个线程的SimpleDateFormat类对象的副本,使每个线程在运行时,各自使用自身绑定的SimpleDateFormat对象,互不干扰,执行性能比较高,推荐在高并发的生产环境使用。

DateTimeFormatter是Java 8中提供的处理日期和时间的类,DateTimeFormatter类本身就是线程安全的,经压测,DateTimeFormatter类处理日期和时间的性能效果还不错(后文单独写一篇关于高并发下性能压测的文章)。所以,推荐在高并发场景下的生产环境使用。

joda-time是第三方处理日期和时间的类库,线程安全,性能经过高并发的考验,推荐在高并发场景下的生产环境使用。

 

点击关注,第一时间了解华为云新鲜技术~

与高并发场景下,6种解决SimpleDateFormat类的线程安全问题方法相似的内容:

高并发场景下,6种解决SimpleDateFormat类的线程安全问题方法

摘要:解决SimpleDateFormat类在高并发场景下的线程安全问题可以有多种方式,这里,就列举几个常用的方式供参考。 本文分享自华为云社区《【高并发】更正SimpleDateFormat类线程不安全问题分析的错误》,作者: 冰 河 。 解决SimpleDateFormat类在高并发场景下的线程

高并发场景下常见的限流算法及方案介绍

现代互联网很多业务场景,比如秒杀、下单、查询商品详情,最大特点就是高并发,而往往我们的系统不能承受这么大的流量,这时候限流熔断就发挥作用了,限制请求数,快速失败,保证系统满负载又不超限。本文为大家介绍几种常见的限流算法及方案

高并发场景下,如何优化服务器的性能

摘要:tcp_nodelay参数主要是对TCP套接字来说的,那对于服务器硬件,如果要使其能够支撑上百万甚至上千万的并发,我们该如何对其进行优化呢? 本文分享自华为云社区《【高并发】高并发场景下如何优化服务器的性能?》,作者: 冰 河 。 写在前面 最近,有小伙伴在群里提问:Linux系统怎么设置tc

StampedLock:高并发场景下一种比读写锁更快的锁

摘要:在读多写少的环境中,有没有一种比ReadWriteLock更快的锁呢?有,那就是JDK1.8中新增的StampedLock! 本文分享自华为云社区《【高并发】高并发场景下一种比读写锁更快的锁》,作者: 冰 河。 什么是StampedLock? ReadWriteLock锁允许多个线程同时读取共

[转帖]高并发场景下JVM调优实践之路

https://www.jianshu.com/p/f5f5f99e2417 一、背景 2021年2月,收到反馈,视频APP某核心接口高峰期响应慢,影响用户体验。 通过监控发现,接口响应慢主要是P99耗时高引起的,怀疑与该服务的GC有关,该服务典型的一个实例GC表现如下图: image image

5个高并发场景优化的衡量指标

今天,我们就来说说在高并发场景下做性能优化有哪些衡量标准,以及做优化时需要注意哪些问题。

如何用ReadWriteLock实现一个通用的缓存中心?

摘要:在并发场景中,Java SDK中提供了ReadWriteLock来满足读多写少的场景。 本文分享自华为云社区《【高并发】基于ReadWriteLock开了个一款高性能缓存》,作者:冰 河。 写在前面 在实际工作中,有一种非常普遍的并发场景:那就是读多写少的场景。在这种场景下,为了优化程序的性能

稳定支撑千万级月活,华为日历背后的英雄

摘要:华为日历月活高达数千万,这使其对支撑业务的数据库提出了巨大挑战:高并发场景下,数据库如何实现快速扩容?海量数据运行,如何确保业务稳定性? 本文分享自华为云社区《稳定支撑千万级月活,华为日历背后的英雄》,作者: GaussDB 数据库。 随着科技进步,手机日历早已融入我们的生活,不仅可以记录时间

架构与思维:4大主流分布式算法介绍(图文并茂、算法拆解)

0 导读 之前的文章中,我们介绍过分布式事务的基础知识,也了解了分布式场景下常见一致性问题和解决方案,对分布式锁和CAS模式有一定的了解,有兴趣的同学可以通过下面链接到作者的两篇相关文章。 五种分布式事务解决方案(图文总结) 高并发下的数据一致性保障(图文全面总结) 1 介绍 本文聚焦高并发场景下分

http1.1 的默认长连接 Connection: keep-alive 与 TCP KeepAlive 之间区别

HTTP 长连接,也称为 HTTP 持久连接(HTTP Persistent Connection)或 HTTP 连接重用,是一种在 HTTP 协议中实现的机制。 在传统的 HTTP 通信中,每个 HTTP 请求和响应都会伴随着 TCP 连接的建立和关闭,这在高并发场景下会增加网络开销和延迟。 而