DB性能跟不上,加缓存就够了?

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

服务端软件开发时通常会把数据存储在DB。而服务端系统遇到的第一个性能瓶颈往往发生在访问DB时。
这时大部分开发会拿出“缓存”通过使用Redis在DB前提供一层缓存数据缓解DB压力提升服务端性能。

在数据库前添加数据缓存常见的性能优化方式

这种添加缓存的策略一定有效吗这种策略在什么情况下是有效的呢理论分析添加缓存最佳策略么
如果我们对访问性能要求高希望数据在1ms乃至100微妙内完成处理我们还能用这个添加缓存的策略么

1 理解局部性原理


Intel 8265U的CPU L1 Cache只有256KL2 Cache有个1MBL3 Cache有12MB。共13MB存储空间如按7美元/1MB的价格计算就要91美元。
内存8GB容量是CPU Cache 600多倍120美元。如按今天价格恐怕不到40美元。128G的SSD和1T的HDD现在的价格加起来也不会超过100美元。虽容量是内存16倍乃至128倍但访问速度不到内存1/1000。

性能和价格的巨大差异给我们工程师带来挑战能不能既享受CPU Cache速度又享受内存、硬盘巨大的容量和低廉的价格呢
想要同时享受到这三点答案就是存储器中数据的局部性原理Principle of Locality。可利用这个原理制定管理和访问数据的策略。这个局部性原理包括时间局部性temporal locality和空间局部性spatial locality这两种策略。

2 时间局部性

如果一个数据被访问了那它在短时间内还会被再次访问。

如小说今天读了一会儿没读完明天还会继续读。同理电子商务系统一个用户打开App看到首屏。推断他应该很快还会再次访问网站的其他内容或页面就将这个用户的个人信息从存储在硬盘的数据库读取到内存的缓存中来。这利用的就是时间局部性。

同一份数据在短时间内会反复多次被访问

3 空间局部性

如果一个数据被访问了那么和它相邻的数据也很快会被访问。

读完了这本书之后感觉这书不错所以就会借阅整套。程序访问了数组首项后多半会循环访问下一项。因为在存储数据的时候数组内的多项数据会存储在相邻的位置。这就好比图书馆会把“哈利波特”系列放在一个书架上摆放在一起加载时也会一并加载。我们去图书馆借书往往会一次性把7本都借回来。

4 相邻的数据会被连续访问

有了时间局部性和空间局部性不用再把所有数据都放在内存也不用都放在HDD而是把访问次数多的数据放在贵但快的存储器把访问次数少的数据放在慢但大点的存储器。
这样组合使用内存、SSD硬盘以及HDD硬盘最低成本提供实际所需的数据存储、管理和访问需求。

5 花最少的钱装下亚马逊的所有商品

通过局部性原理利用不同层次存储器的组合究竟会有什么样的好处。

提供一个亚马逊电商网站。假设里面有6亿件商品如果每件商品需要4MB的存储空间需2400TB = 6亿 × 4MB数据存储。

如把数据都放在内存就需3600万美元 = 2400TB/1MB × 0.015美元 = 3600万美元。但这6亿件商品不是每件商品都会被经常访问。如有Kindle也一定有无人问津商品如缅甸语词典。

如只在内存里放前1%热门商品即600万件热门商品而把剩下商品放在机械式HDD硬盘则需存储成本下降到45.6万美元 = 3600 万美元 × 1% + 2400TB / 1MB × 0.00004 美元是原来成本的1.3%左右。
这就是时间局部性。把有用户访问过数据加载到内存一旦内存放不下就把最长时间没在内存被访问过的数据从内存移走这就是LRULeast Recently Used。
热门商品被访问得多就会始终被保留在内存冷门商品被访问得少就只存放在HDD数据读取也都是直接访问硬盘。即使加载到内存中也会很快被移除。越热门越容易在内存中找到也就更好地利用了内存的随机访问性能。

只放600万件商品真的可以满足我们实际的线上服务请求吗
要看LRU缓存命中率Hit Rate/Hit Ratio即访问的数据中可在我们设置的内存缓存中找到的占比。

内存随机访问请求需要100ns。极限情况下内存可以支持1000万次随机访问。我们用了24TB内存如果8G一条的话意味着有3000条内存可以支持每秒300亿次 = 24TB/8GB × 1s/100ns访问。以亚马逊2017年3亿的用户数来看我们估算每天的活跃用户为1亿这1亿用户每人平均会访问100个商品那么平均每秒访问的商品数量就是12万次。

但如数据没有命中内存那么对应的数据请求就要访问到HDD磁盘了。一块HDD硬盘只能支撑每秒100次的随机访问2400TB的数据以4TB一块磁盘来计算有600块磁盘也就是能支撑每秒 6万次 = 2400TB/4TB × 1s/10ms 的随机访问。

这意味所有商品访问请求都直接到了HDD磁盘HDD磁盘支撑不了这样的压力。我们至少要50%的缓存命中率HDD磁盘才能支撑对应的访问次数。不然的话我们要么选择添加更多数量的HDD硬盘做到每秒12万次的随机访问或者将HDD替换成SSD硬盘让单个硬盘可以支持更多的随机访问请求。

这只是一个简单估算。实际应用程序中查看一个商品数据意味着不止一次随机内存或随机磁盘访问。对应数据存储空间也不止要考虑数据还需要考虑维护数据结构的空间而缓存的命中率和访问请求也要考虑均值和峰值的问题。

估算过程要理解如何进行存储器的硬件规划。要考虑硬件的成本、访问的数据量以及访问的数据分布然后根据这些数据的估算来组合不同的存储器能用尽可能低的成本支撑所需要的服务器压力。而当你用上了数据访问的局部性原理组合起了多种存储器你也就理解了怎么基于存储器层次结构来进行硬件规划了。

6 总结

实际的计算机日常的开发和应用中对于数据的访问总是会存在一定的局部性。有时候这个局部性是时间局部性就是我们最近访问过的数据还会被反复访问。有时候这个局部性是空间局部性就是我们最近访问过数据附近的数据很快会被访问到。

而局部性的存在使得我们可以在应用开发中使用缓存这个有利的武器。比如通过将热点数据加载并保留在速度更快的存储设备里面我们可以用更低的成本来支撑服务器。

通过亚马逊这个例子我们可以看到我们可以通过快速估算的方式来判断这个添加缓存的策略是否能够满足我们的需求以及在估算的服务器负载的情况下需要规划多少硬件设备。这个“估算+规划”的能力是每一个期望成长为架构师的工程师必须掌握的能力。

遇到性能问题特别是访问存储器的性能问题的时候是否可以简单地添加一层数据缓存就能让问题迎刃而解呢
亚马逊网站商品数据的例子似乎给了我们一个“Yes”。那这个答案是否放之四海皆准呢下回分解

参考

  • 《计算机组成与设计硬件/软件接口》的5.1~5.2小节
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6