小景最近在做系统查询接口的压测相关的工作,其中涉及到了查询接口的数据库缓存相关的内容,在这里做一个汇总和思维发散,顺便简单说下自己的心得:
针对系统的查询接口,首次压测执行的时候TPS较低,平均响应时间较高,后续的查询中,TPS和平均相应时间较第一次比有较为明显的提升,这里考虑到时Oracle数据库缓存的原因:
首先要明确的是,Oracle数据库查询中有缓存的概念。数据库管理系统通常会对执行过的查询结果、执行计划或者数据页进行缓存,以提高后续相同查询的性能。
在 Oracle 数据库中,有几种常见的缓存机制,每种都在不同层次上提高查询性能:
-
数据 Buffer Cache(数据块缓存):这是数据库内存中的一个重要部分,用于存储最常用的数据块。当数据库需要读取数据时,它首先检查 Buffer Cache,如果数据块已经在缓存中,则不需要再从磁盘读取,而是直接从内存中获取数据。这减少了磁盘 I/O 操作,提高了数据读取的速度。
-
Shared Pool(共享池):共享池是另一个重要的内存区域,用于存储 SQL 语句的执行计划、共享 SQL 区域和其他共享的内存结构。当你执行一个 SQL 查询时,Oracle 会检查共享池中是否已经有了该查询的执行计划。如果有,它可以直接使用共享的执行计划,而不需要重新生成,提高了查询的执行效率。
-
Library Cache(库缓存):库缓存是共享池的一个组成部分,其中存储了 SQL 语句的解析结果和执行计划。这些信息的缓存减少了 SQL 语句的重新解析和优化时间,提高了查询的性能。
-
Data Dictionary Cache(数据字典缓存):数据字典缓存存储了系统元数据信息,比如表的结构、索引、权限等信息。这些信息的缓存减少了对数据字典的频繁访问,提高了系统的性能。
这些缓存层次相互协作,以提高查询的性能和数据库整体的效率。通过缓存常用的数据块、执行计划以及元数据信息,Oracle 数据库可以加快查询的速度,并降低系统对磁盘的 I/O 访问,从而提高整体性能。
那么上述执行了相同的查询两次,第二次查询的耗时比第一次短可能有多种原因:
- 数据缓存:数据库中的数据可能在第一次查询时被加载到缓存中。当相同的数据被第二次查询时,它可能仍然保留在缓存中,因此查询能够更快地获取数据,而不需要从磁盘读取。
底层逻辑:数据库通过 Buffer Cache 缓存经常读取的数据块,减少了对磁盘的读取。如果数据块在第一次查询时被读取到缓存中,它会在一段时间内保持在内存中,以备再次读取。第二次查询时,如果所需的数据仍在 Buffer Cache 中,数据库不需要再次访问磁盘,从而提高查询速度。
- 执行计划缓存:数据库可能已经为第一次查询生成了执行计划,并将其缓存。在第二次查询时,相同的执行计划可以被重用,避免了重新生成执行计划所带来的开销。
底层逻辑:当查询语句被执行时,数据库会生成执行计划来决定如何检索数据。数据库可以将执行计划缓存起来,以备将来的查询使用。第二次查询时,如果相同的执行计划已经被缓存,数据库不需要重新生成执行计划,直接使用缓存的执行计划,节省了重新优化查询的时间。
- 数据 Block 的重复读取:数据库中的数据块可能由多个用户频繁读取。第一次查询时,数据块从磁盘加载到缓存。第二次查询时,由于数据块已经在缓存中,其他用户的查询可能已经导致数据块存在于缓存中,从而减少了读取数据块所需的时间。
底层逻辑:当一个数据块被多次读取,它可能会留在数据库的缓存中。这种情况发生在多个查询都使用相同的数据块时,比如在多个用户或查询之间共享数据块。如果一个数据块在第一次查询中被加载到缓存中,并且其他查询也使用了同一块数据,它可能会保留在缓存中,从而使第二次查询更快。
- 数据修改:在第一次查询后,可能没有对查询所用到的数据块进行修改,这样数据块可以保持在缓存中。因此,第二次查询时,数据仍在缓存中,查询速度更快。
底层逻辑:当数据块在查询后没有发生变化,它可能会继续保留在数据库的缓存中。如果数据块在第一次查询时被加载到缓存中,而在第二次查询前没有发生修改,它仍将保留在缓存中,使得第二次查询更快。
- 系统负载:第一次查询可能与其他并行操作同时进行,例如其他大型查询或数据加载过程。这可能会导致系统资源的竞争,从而减慢查询的执行。第二次查询时,系统负载减轻,资源更为充足,因此查询速度更快。
底层逻辑:第一次查询时,系统可能处于高负载状态,有可能是有其他大型查询或者并发操作正在执行,这会使得系统资源分配不均。这可能导致数据库和服务器的资源竞争,降低了第一次查询的速度。在第二次查询时,如果系统负载较低,资源更为充足,那么查询可能会更快。
这些因素都可能影响了相同查询两次执行时的耗时差异。数据库中的缓存、并发操作、数据修改以及系统负载等都会对查询性能产生影响。
那么针对上述可能的原因,系统在做压力测试的时候,具体怎么操作才能避开上述的原因呢?小景给出了一些避坑点:
-
冷启动环境:在进行压力测试之前,重启数据库以确保缓存被清空。这将确保数据库在测试开始时处于相对清洁的状态,不会受到之前执行过的查询、缓存或执行计划的影响。
-
预热环境:在进行正式测试之前,预先运行一些基准查询,以便数据库缓存中有一些热点数据。这有助于在真正的压力测试开始之前,建立一些常用数据的缓存,模拟真实场景。
-
使用隔离环境:尽可能在一个相对独立的环境中进行测试,以避免其他应用或用户活动对系统负载的干扰。这可以通过使用专门用于测试的数据库实例或独立的服务器进行实现。
-
多次测试和平均值:进行多次测试并取平均值,而不仅仅是一次测试。因为数据库的性能在不同时间点可能会有所不同,进行多次测试并取平均值有助于得到更可靠的结果。
5.监控系统资源:对系统的资源使用情况进行监控,包括 CPU 使用率、内存使用情况、磁盘 I/O 等。这有助于识别可能导致性能变化的系统负载。
- 隔离测试过程:尽可能将不同的测试过程进行隔离,确保不同测试之间不会相互影响,比如在每次测试之间清理缓存、重置环境等。
通过这些方法,你可以尽量减少外部因素对测试结果的影响,从而获得更为准确和可靠的压力测试结果。
上述几点还都比较好理解,那么有小伙伴可能会问了,监控系统资源的时候,一般都是看哪几个指标?有没有具体的标准?比如,CPU 使用率、内存使用情况、磁盘 I/O 等达到了什么数值的时候,说明系统负载较高?或者系统达到了资源瓶颈?下面小景就详细说下监控系统资源这点:
-
CPU 使用率:CPU 使用率是非常重要的指标之一。它表示 CPU 的工作负荷,通常以百分比来表示。一般来说,超过 70-80% 的持续 CPU 使用率可能表明系统负载较高,超过 90% 则表示系统可能面临瓶颈。
-
内存使用情况:监控可用内存、使用情况以及交换空间的使用情况。当系统内存使用达到接近或超过总内存的80%时,可能表明系统内存资源紧张,可能导致性能下降。
-
磁盘 I/O:监控磁盘 I/O 操作,包括读取和写入速率。如果磁盘 I/O 达到磁盘的最大容量或磁盘吞吐量达到饱和状态,可能会成为系统的瓶颈。
-
网络流量:对于需要大量网络传输的系统,监控网络带宽、网络延迟以及网络连接数。高网络流量可能导致网络拥塞,影响系统性能。
总结:标准或阈值值因系统和环境而异,没有单一的标准适用于所有情况。通常来说,这些数值的超过并不能直接说明系统一定存在问题,需要综合考虑其他因素,比如系统负载的特性、硬件规格、应用程序特点等等。
关键是了解系统的基线性能和常规行为,通过观察系统在正常情况下的指标,然后对照测试期间的数值变化来评估系统的性能和负载情况。如果在测试期间出现异常,例如指标异常高或异常低,可能意味着系统在承受压力时出现了瓶颈。
那么可能又有小伙伴会问了,上述第三点所说的网络通信,怎么判断应用服务器和数据库服务器之间的通信是优秀还是良好,还是不好呢?具体是怎么操作?小景给出了一些自己的建议:
-
Ping测试 :使用 `ping` 命令测试应用服务器和数据库服务器之间的网络连接。较低的延迟和较少的丢包率通常是良好通信的指标。命令格式为:`ping <数据库服务器IP>`。替换
<数据库服务器IP>
为你数据库服务器的实际 IP 地址。这条命令会发送 ICMP 请求到目标服务器并接收 ICMP 响应,从而可以评估到达目标服务器的延迟和丢包率。较高的延迟和较高的丢包率可能表明网络连接存在问题。 -
网络监控工具:使用网络监控工具来实时监控应用服务器和数据库服务器之间的网络流量、延迟和丢包率。工具如Wireshark、tcpdump等,能够提供详细的网络数据包信息。通过分析数据包,可以确定通信中是否存在异常或潜在问题。
-
传输速率 :
iperf
是一个网络性能测试工具,它可以测量网络带宽和吞吐量。首先,你需要在应用服务器和数据库服务器上分别安装iperf
。使用工具如`iperf`来测试应用服务器和数据库服务器之间的带宽和传输速率。这可以帮助你确定网络的最大吞吐量。`iperf` 可以在服务器之间进行速率测试。命令格式为:`iperf -c <数据库服务器IP>`。
这条命令会向数据库服务器发送 TCP 数据包,以测试应用服务器到数据库服务器之间的带宽和传输速率。在数据库服务器上需要运行 iperf
服务端来接受连接。如果数据库服务器上没有安装 iperf
,你需要在数据库服务器上运行以下命令安装 iperf
服务端:
sudo apt-get install iperf
sudo yum install iperf
安装完毕后,在数据库服务器上执行以下命令来运行 iperf
服务端:
iperf -s
这将启动 iperf
服务端以接收来自应用服务器的连接,并进行网络带宽测试。
- 应用程序响应时间:在进行压力测试时,观察应用程序的响应时间,尤其是与数据库通信相关的操作。较长的响应时间可能是网络通信问题的表现。
-
-
-
监控工具:使用监控工具,比如 New Relic、AppDynamics 等,这些工具提供实时监控应用程序的性能、响应时间、请求处理等信息。
-
自定义监控脚本:编写自定义脚本来模拟用户请求并记录应用程序的响应时间。你可以使用类似
curl
或ab
(Apache Benchmark)这样的命令行工具,以及编程语言(如Python、Java)来执行请求并记录响应时间。
-
-
- 系统日志和监控工具:审查系统的日志记录和使用监控工具(如Nagios、Zabbix等)来查看网络接口的使用情况、错误信息、带宽利用率等。异常或错误的日志信息可能提示着网络通信方面的问题。
-
-
-
系统日志:系统日志位于
/var/log
或类似的位置。不同的系统日志记录了网络、应用程序、数据库和系统事件。你可以查看日志文件(如syslog
、messages
、dmesg
)来检查网络连接、错误、警告或其他与通信相关的信息。 -
监控工具:使用专门的监控工具,比如 Nagios、Zabbix、ELK Stack 等,来监控系统日志和事件。这些工具可以自动分析和报警,帮助你更好地了解系统的状态和问题。
-
-
这些方法可以帮助你评估应用服务器和数据库服务器之间的通信质量。通过监控网络延迟、丢包率、带宽利用率和响应时间,可以更全面地了解通信情况,以及是否存在网络通信方面的瓶颈或问题。
最后,希望小景的这篇文章可以帮助您解决实际工作中的问题,有什么问题可以评论区或者关注我的微信公众号来交流。