高性能程序设计,缓存为王

背景

我们在程序设计时,有一个极其重要的非功能性指标:性能,总是无时无刻不缠绕在程序员的脑海,尤其是我们开发的面向大众的Web服务, 络接口等程序。

当然,高性能的程序设计也会更加复杂,开发也有更大难度。

这次的内容,我们面向高性能程序设计方向,来讲一讲其中最核心最重要的缓存。

大纲:

  • 1 高性能程序与时间、空间的关系

  • 2 无处不在的缓存,硬件与软件

  • 3 系统中的缓存设计

  • 4 总结,缓存为王

0 找找看,人体中的缓存、缓冲区

1.1 性能,速度与时间

  • 吞吐率:单位时间内处理的请求数

  • 吞吐量:对 络、设备、端口、虚电路或其他设施,单位时间内成功地传送数据的数量

  • TPS:每秒钟系统能够处理事务或交易的数量

  • 性能=速度=数量/时间,单位时间内处理的数量越多,性能越好

1.2 系统性能预估

CPU密集型,如:数据排序

假设:单次请求耗时 Tms,服务器CPU数量 C核,集群的服务器数量S台

IO密集型,如:依赖大量 络API/数据库/文件(IO耗时)

服务线程数量预估

1.3 降低单次请求执行时间

减少CPU运算量

减少IO耗时

利用缓存

最好的优化手段就是砍需求,没有代码就有最好的性能。

1.4 缓存,空间换时间

增加的缓存空间

增加的处理逻辑

减少的处理时间

离CPU越近的数据,处理越快;减少的处理逻辑就是优化的时间。缓存就是这个法宝。

1.5 缓存,是否多多益善

下面三种情况建议尽量使用缓存来做优化。

减少的处理时间显著(性能差异明显)

增加空间有限(成本提高)

增加的处理有限(开发难度,运算次数)

1.6 总结,高性能程序与时间、空间的关系

高性能程序设计,重点关注

空间换时间,缓存的优势

避免缓存的陷阱

2 无处不在的缓存,硬件与软件

CPU内的寄存器/L1/L2/L3

  • 速度不一样

  • 容量不一样

  • 成本不一样

计算机内存

  • 容量更大

  • 成本更低

  • 速度稍慢(比硬盘、 络快很多)

更多参考: 并发编程与锁的底层原理(https://www.imooc.com/article/283248)

2.2 硬盘内的缓存

SATA传来的数据和盘片的实际操作间加一个缓冲

  • HDD的延迟是ms级别,缓存是ns级,相差数万倍

  • 缓存容量增加,提高命中率

  • 突然掉电导致数据丢失的风险增大

  • 固态混合硬盘,内置8G/16G固态硬盘,缓存容量更大

  • 固态硬盘,随机读写速度更快

为什么机械硬盘的缓存不是越大越好/p>

(https://www.zhihu.com/question/27030135)

缓存容量增加,带来的成本提高,突然掉电导致数据丢失的风险增大

2.3 卡的发送/接收缓存

发送缓存

  • 卡有包就发,包太多了就放入缓存队列,缓存满了就丢包并且告诉系统丢包了

  • TCP协议具有流控和拥塞检测功能,防止发包太快造成丢包(UDP不可靠传输)

  • 卡接收数据,放入接收缓存,一次数据接收完成后, 卡驱动程序,向CPU发送信 ,提示 卡有新数据到来。

  • 操作系统从 卡的接收缓冲队列中读取数据,交给应用程序处理。

2.4 操作系统的缓存

缓冲文件系统

  • 在内存开辟一个“缓冲区”,为程序中的每一个文件使用(读写文件先操作缓冲区)

  • fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等

络相关缓存设置

  • /proc/sys/net/core/wmem_max 最大socket写buffer

  • /proc/sys/net/core/rmem_max 最大socket读buffer

  • /proc/sys/net/ipv4/tcp_wmem TCP写buffer

  • /proc/sys/net/ipv4/tcp_rmem TCP读buffer

  • /proc/sys/net/core/netdev_max_backlog 进入包的最大设备队列

  • /proc/sys/net/core/somaxconn listen()的默认参数,挂起请求的最大数量

  • /proc/sys/net/ipv4/tcp_max_syn_backlog 进入SYN包的最大请求队列

操作系统磁盘缓存,可以减少磁盘机械操作。更多参考:

不带缓冲区open和带缓冲区的fopen的区别

(https://blog.csdn.net/tanqiuwei/article/details/20641965)

linux 内核参数优化

(https://www.cnblogs.com/weifeng1463/p/6825532.html)

2.5 程序设计语言的缓存

分布式 络

  • 全国/全球多地部署很多Web服务器缓存节点

  • DNS动态解析,让客户端请求就近访问到Web服务器缓存节点

Web内容缓存

  • 缓存源服务器的内容,有缓存时就不需要回源

  • 可以支持目录规则、文件扩展名等设置缓存策略

  • 可以手动刷新指定目录、文件的缓存数据

2.8 DNS域名解析

Web内容缓存

  • 客户端直接读取缓存,减少对Web服务器的请求

  • 强制缓存 cache-control, expires (from memory cache, from disk cache)

  • 协商缓存 etag, If-None-Match, last-modified, If-Modified-Since (304 not modify)

    更多参考:

    • 彻底理解浏览器的缓存机制

      (https://juejin.im/entry/5ad86c16f265da505a77dca4)

    • 详说 Cookie, LocalStorage 与 SessionStorage

      (https://jerryzou.com/posts/cookie-and-web-storage/)

    2.10 总结,无处不在的缓存,硬件和软件

    数据模型

    • 用户,板块,主题,帖子,回复

    页面

    • 首页,板块帖子列表页,帖子详情页,用户资料页

    操作

    • 浏览,发帖,回帖,置顶

    缓存数据

    • 全量永久缓存:用户(uid -> map),板块(all -> json),置顶帖(all -> json)

    • 部分临时缓存:帖子列表页数据(多种排序, fid-displayorder -> tids), 主题浏览量(tid -> views),帖子数据(tid -> map),用户帖子列表页数据(uid -> json)

    • 页面缓存:首页,帖子详情页

    3.2 电商系统的缓存设计

    3.4 缓存设计,较好场景,临时缓存

    数据读多写少,读取速度慢

    • 用户、内容数据,如:用户信息,帖子信息等

    • 缓存快过数据库

    数据占用空间较大

    • 帖子内容,整页缓存

    • 过期或者未命中再从数据库读取

    保证较高的命中率,90%以上

    • 缓存容量较大,过期/失效的缓存减少,命中率提高

    • 更新的频率降低,命中率提高

    • 更新的时候主动更新缓存,命中率提高

    • 合适的缓存淘汰策略,FIFO/LRU/LFU/TTL/RANDOM

    3.5 缓存设计,特殊场景,性能优先

    如果没有缓存的情况下,100亿的客户端请求,最后落到数据服务器上会有上万亿的IO操作。

    老司机箴言:

    • 设计时,分层分级。

    • 执行时,少查少写少依赖,Less is more。

    • 别让硬盘抗性能,别让内存保持久,别让 线抗稳定。

    高性能程序设计的漫漫求索之路

    如果喜欢老师这篇文章,可以在下方评论区进行提问,文章中涉及的部分参考链接也可以戳原文链接去打开~



    ● 

    ● 

    ● 

    ● 

    —  —

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年5月2日
下一篇 2019年5月2日

相关推荐