HTTP协议进阶:Keep-Alive、缓存机制与内容协商

HTTP/1.0 vs HTTP/1.1 HTTP/1.0的问题 短连接(每次请求都要三次握手): 客户端 → 服务器: SYN(握手) 客户端 ← 服务器: SYN-ACK 客户端 → 服务器: ACK 客户端 → 服务器: GET /index.html 客户端 ← 服务器: HTTP/1.0 200 OK 客户端 → 服务器: FIN(挥手) 下一个请求又要重新握手! 问题: 每个请求都要建立TCP连接(+1.5 RTT延迟) 频繁握手挥手,浪费资源 服务器TIME_WAIT状态过多 HTTP/1.1的改进 1. 持久连接(Keep-Alive):默认开启 # HTTP/1.1请求 GET /api/users HTTP/1.1 Host: api.example.com Connection: keep-alive # HTTP/1.1响应 HTTP/1.1 200 OK Connection: keep-alive Keep-Alive: timeout=5, max=100 一个TCP连接,多个HTTP请求: 客户端 → 服务器: 三次握手 客户端 → 服务器: GET /api/users 客户端 ← 服务器: 200 OK 客户端 → 服务器: GET /api/orders # 复用连接 客户端 ← 服务器: 200 OK 客户端 → 服务器: GET /api/products # 复用连接 客户端 ← 服务器: 200 OK ...(5秒后无请求,关闭连接) 2. 管道化(Pipelining):不等响应,连续发送请求 ...

2025-11-20 · maneng

Redis第一性原理:为什么我们需要缓存?

一、引子:商品详情接口的性能进化之路 想象你正在开发一个电商平台的商品详情页面,每次用户访问都需要查询商品基本信息、品牌信息、类目信息、库存信息和商品图片。让我们看看三种不同的实现方式,以及它们各自的性能表现。 1.1 场景A:无缓存(直接查数据库) 这是最直接的实现方式:每次请求都查询数据库。 @Service public class ProductService { @Autowired private ProductRepository productRepository; @Autowired private BrandRepository brandRepository; @Autowired private CategoryRepository categoryRepository; @Autowired private InventoryRepository inventoryRepository; @Autowired private ProductImageRepository productImageRepository; /** * 查询商品详情(每次请求都查数据库) * 平均耗时:100ms * QPS上限:500 */ public ProductDetailVO getProductDetail(Long productId) { // 1. 查询商品基本信息(20ms) Product product = productRepository.findById(productId); if (product == null) { throw new ProductNotFoundException("商品不存在:" + productId); } // 2. 查询品牌信息(20ms) Brand brand = brandRepository.findById(product.getBrandId()); // 3. 查询类目信息(20ms) Category category = categoryRepository.findById(product.getCategoryId()); // 4. 查询库存信息(20ms) Inventory inventory = inventoryRepository.findByProductId(productId); // 5. 查询商品图片(20ms,可能有N+1查询问题) List<ProductImage> images = productImageRepository.findByProductId(productId); // 6. 组装返回对象 ProductDetailVO vo = new ProductDetailVO(); vo.setProductId(product.getId()); vo.setProductName(product.getName()); vo.setPrice(product.getPrice()); vo.setBrandName(brand.getName()); vo.setCategoryName(category.getName()); vo.setStock(inventory.getStock()); vo.setImages(images); return vo; } } 性能数据(压测工具:JMeter,1000并发): ...

2025-11-03 · maneng

从HashMap到Redis:分布式缓存的演进

一、引子:一个用户会话缓存的演进之路 假设你正在开发一个电商网站的用户会话管理功能。每次用户请求都需要验证身份,最初的实现是每次都查询数据库,但随着用户量增长,数据库压力越来越大。让我们看看这个功能如何一步步演进,从最简单的HashMap到最终的Redis分布式缓存。 1.1 场景0:无缓存(每次查数据库) 最直接的实现:每次请求都查询数据库验证用户身份。 @RestController public class UserController { @Autowired private UserRepository userRepository; /** * 获取用户信息(每次查数据库) * 问题:数据库压力大,响应慢 */ @GetMapping("/api/user/info") public UserVO getUserInfo(@RequestHeader("token") String token) { // 1. 根据token查询用户ID(查数据库) Long userId = tokenRepository.findUserIdByToken(token); if (userId == null) { throw new UnauthorizedException("未登录"); } // 2. 查询用户详细信息(查数据库) User user = userRepository.findById(userId); if (user == null) { throw new UserNotFoundException("用户不存在"); } return convertToVO(user); } } 性能数据: 指标 数值 说明 平均响应时间 50ms 2次SQL查询 QPS上限 1000 数据库连接池限制 数据库压力 100% 每次请求都查库 问题: ...

2025-11-03 · maneng

Redis第一性原理:为什么我们需要缓存?

一、引子:商品详情接口的性能进化之路 想象你正在开发一个电商平台的商品详情页面,每次用户访问都需要查询商品基本信息、品牌信息、类目信息、库存信息和商品图片。让我们看看三种不同的实现方式,以及它们各自的性能表现。 1.1 场景A:无缓存(直接查数据库) 这是最直接的实现方式:每次请求都查询数据库。 @Service public class ProductService { @Autowired private ProductRepository productRepository; @Autowired private BrandRepository brandRepository; @Autowired private CategoryRepository categoryRepository; @Autowired private InventoryRepository inventoryRepository; @Autowired private ProductImageRepository productImageRepository; /** * 查询商品详情(每次请求都查数据库) * 平均耗时:100ms * QPS上限:500 */ public ProductDetailVO getProductDetail(Long productId) { // 1. 查询商品基本信息(20ms) Product product = productRepository.findById(productId); if (product == null) { throw new ProductNotFoundException("商品不存在:" + productId); } // 2. 查询品牌信息(20ms) Brand brand = brandRepository.findById(product.getBrandId()); // 3. 查询类目信息(20ms) Category category = categoryRepository.findById(product.getCategoryId()); // 4. 查询库存信息(20ms) Inventory inventory = inventoryRepository.findByProductId(productId); // 5. 查询商品图片(20ms,可能有N+1查询问题) List<ProductImage> images = productImageRepository.findByProductId(productId); // 6. 组装返回对象 ProductDetailVO vo = new ProductDetailVO(); vo.setProductId(product.getId()); vo.setProductName(product.getName()); vo.setPrice(product.getPrice()); vo.setBrandName(brand.getName()); vo.setCategoryName(category.getName()); vo.setStock(inventory.getStock()); vo.setImages(images); return vo; } } 性能数据(压测工具:JMeter,1000并发): ...

2025-11-03 · maneng

从HashMap到Redis:分布式缓存的演进

一、引子:一个用户会话缓存的演进之路 假设你正在开发一个电商网站的用户会话管理功能。每次用户请求都需要验证身份,最初的实现是每次都查询数据库,但随着用户量增长,数据库压力越来越大。让我们看看这个功能如何一步步演进,从最简单的HashMap到最终的Redis分布式缓存。 1.1 场景0:无缓存(每次查数据库) 最直接的实现:每次请求都查询数据库验证用户身份。 @RestController public class UserController { @Autowired private UserRepository userRepository; /** * 获取用户信息(每次查数据库) * 问题:数据库压力大,响应慢 */ @GetMapping("/api/user/info") public UserVO getUserInfo(@RequestHeader("token") String token) { // 1. 根据token查询用户ID(查数据库) Long userId = tokenRepository.findUserIdByToken(token); if (userId == null) { throw new UnauthorizedException("未登录"); } // 2. 查询用户详细信息(查数据库) User user = userRepository.findById(userId); if (user == null) { throw new UserNotFoundException("用户不存在"); } return convertToVO(user); } } 性能数据: 指标 数值 说明 平均响应时间 50ms 2次SQL查询 QPS上限 1000 数据库连接池限制 数据库压力 100% 每次请求都查库 问题: ...

2025-11-03 · maneng

缓存的第一性原理:为什么需要Redis?

引言 在开始学习Redis之前,我们先不谈具体的命令和用法,而是回到原点思考一个问题:为什么我们需要Redis? 这不是一个简单的问题。如果只是回答"因为它快"或"因为大家都在用",那就失去了深入理解的机会。让我们从第一性原理出发,理解缓存的本质,以及Redis在现代架构中的真正价值。 一、存储的时空矛盾 1.1 计算机存储的金字塔 计算机系统中存在一个永恒的矛盾:速度快的存储容量小且昂贵,容量大的存储速度慢且廉价。 让我们看看存储层次结构(从快到慢): CPU寄存器 ← 1ns ← 几KB ← 最快最贵 L1 Cache ← 1-2ns ← 几十KB ← L2 Cache ← 4-10ns ← 几百KB ← L3 Cache ← 20-40ns ← 几MB ← 内存(RAM) ← 100ns ← 几GB ← Redis在这里 SSD硬盘 ← 50-150μs ← 几百GB ← 机械硬盘 ← 5-10ms ← 几TB ← 网络存储 ← >10ms ← 无限大 ← 数据库在这里 关键观察: CPU寄存器访问需要 1纳秒 内存访问需要 100纳秒(慢100倍) SSD访问需要 100微秒(慢1000倍) 机械硬盘访问需要 10毫秒(慢100,000倍) 网络数据库访问需要 >10毫秒(慢100,000倍以上) 1.2 真实世界的类比 如果把CPU访问寄存器比作1秒,那么: ...

2025-01-21 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...