计算机组成原理:局部性原理---数据库性能跟不上,加个缓存就好了?

引入

  • 平时进行服务器软件开发的时候,我们通常会把数据存储到数据库中。而服务端系统遇到的第一个性能瓶颈,往往就发生在访问数据库的时候。这个时候,经常问在数据库前面通过redis或者memcached添加一层缓存的数据,来缓解数据库的压力,提升服务器的程序性能
  • 问题是,这种添加缓存的策略一定是有效的吗?或者说,这种策略在什么时候是最有效的呢?添加缓存一定是我们的最佳策略吗?进一步地,如果我们对于访问性能的要求非常高,希望数据在 1 毫秒,乃至 100 微妙内完成处理,我们还能用这个添加缓存的策略么?

在这里插入图片描述

局部性原理

在这里插入图片描述

不同的存储器设备之间,访问速度、价格和容量都有几十乃至上千倍的差异。性能和价格的巨大差异,给我们带来了一个挑战:我们能不能即享受CPU Cache的速度,又享受内存、硬盘巨大的容量和低廉的价格呢?

答案是:通过存储器中数据的局部性原理就可以同时享受到这三点了。我们可以利用这个局部性原理,来指定管理和访问数据的策略。这个局部性原理包括时间局部性空间局部性

  • 时间局部性:如果一个数据被访问了,那么它在短时间内还会被再次访问。举个例子
    • 《哈利波特与魔法石》这本小说,我今天读了一会儿,没有读完,明天还会继续。
    • 同理,在一个电子商务系统中,如果一个用户打开了App,看到了首屏。我们推断他应该很快还会再次访问网站的其他内容或者数据,我们就将这个用户的个人信息,从存储在硬件中的数据库读取到内存的缓存中来。这利用的就是时间局部性。
      在这里插入图片描述
  • 空间局部性:如果一个数据被访问到了,那么和它相邻的数据也很快会被访问到。举个例子:
    • 读完《哈利波特与魔法石》之后,可能会觉得这本书不错,于是就会去借阅整套“哈利波特”。图书馆会把《哈利波特》系统放在一个书架上,摆放到一起。我们去图书馆借书,往往会一次性把 7 本都借回来。
    • 程序中,在访问数据的首项之后,多半会循环访问它的下一项。因此,在存储数据的时候,数组内的多项数据都会加载到相邻的位置。加载的时候,往往会一并加载
      在这里插入图片描述

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

局部性原理真是计算机各类优化的基石,小到cpu cache,大到cdn。而且不仅仅是存储,java的jit也是利于局部性优化性能。任何东西只要不是均匀分布的,就有优化空间。

如何花最少的钱,装下亚马逊的所有商品?

我们现在要提供一个亚马逊这样的电商网站。我们假设里面有 6 亿件商品,如果每件商品需要 4MB 的存储空间(考虑到商品图片的话,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% 左右。

这里我们用的就是时间局部性。我们把有用户访问过的数据,加载到内存中,一旦内存里面放不下了,我们就把最长时间没有在内存中被访问过的数据,从内存中移走,这就是LRUU(Least 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 硬盘,让单个硬盘可以支持更多的随机访问请求
    在这里插入图片描述
    当然,这里我们只是一个简单的估算。在实际的应用程序中,查看一个商品的数据可能意味着不止一次的随机内存或者随机磁盘的访问。对应的数据存储空间也不止要考虑数据,还需要考虑维护数据结构的空间,而缓存的命中率和访问请求也要考虑均值和峰值的问题。

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

总结

我们讲解了计算机存储器层次结构中最重要的一个优化思路,就是局部性原理。

  • 在实际的计算机日常的开发和应用中,我们对于数据的访问总是会存在一定的局部性。有时候,这个局部性是时间局部性,就是我们最近访问过的数据还会被反复访问。有时候,这个局部性是空间局部性,就是我们最近访问过数据附近的数据很快会被访问到。
  • 而局部性的存在,使得我们可以在应用开发中使用缓存这个有利的武器。比如,通过将热点数据加载并保留在速度更快的存储设备里面,我们可以用更低的成本来支撑服务器

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值