Linux 스왑은 디스크의 영역인 Linux 스왑 파티션을 의미합니다. 파티션, 파일 또는 이 둘의 조합일 수 있습니다. 스왑은 Windows의 가상 메모리, 즉 메모리가 있을 때와 유사합니다. 부족합니다. 하드 디스크 공간의 일부를 메모리로 가상화하여 메모리 용량 부족 문제를 해결합니다.
이 튜토리얼의 운영 환경: linux5.9.8 시스템, Dell G3 컴퓨터.
linux swap
Linux 스왑 파티션(스왑) 또는 메모리 교체 공간(스왑 공간)은 디스크의 영역으로 파티션, 파일 또는 이들의 조합이 될 수 있습니다.
SWAP 기능은 Windows 시스템의 "가상 메모리"와 유사합니다. 물리적인 메모리가 부족할 경우 하드디스크 공간의 일부를 SWAP 파티션(가상적으로 메모리로 변환)으로 사용하여 메모리 용량 부족 문제를 해결합니다.
SWAP은 이름에서 알 수 있듯이 프로세스가 OS에 메모리를 요청하고 메모리가 부족하다는 사실을 발견하면 OS는 메모리에서 일시적으로 사용되지 않는 데이터를 교체하여 SWAP 파티션에 배치합니다. 교환하세요. 프로세스에 이 데이터가 필요하고 OS가 여유 물리적 메모리가 있음을 발견하면 SWAP 파티션의 데이터를 다시 물리적 메모리로 스왑합니다. 이 프로세스를 SWAP IN이라고 합니다.
물론, 스왑 크기에는 상한이 있습니다. 스왑이 모두 사용되면 운영 체제는 OOM-Killer 메커니즘을 트리거하여 메모리를 해제하기 위해 가장 많은 메모리를 소비하는 프로세스를 종료합니다.
왜 데이터베이스 시스템은 스왑을 싫어하나요?
분명히 스왑 메커니즘의 원래 의도는 물리적 메모리 부족으로 인한 당혹감을 완화하고 OOM 프로세스를 직접 거칠게 만드는 것입니다. 그러나 솔직히 말해서 MySQL, Oracal, MongoDB 또는 HBase 등 거의 모든 데이터베이스는 스왑을 좋아하지 않습니다. 이는 주로 다음 두 가지 측면과 관련이 있습니다:
1. 데이터베이스 시스템은 일반적으로 응답 지연에 민감합니다. 메모리 대신 스왑을 사용하면 데이터베이스 서비스 성능이 필연적으로 허용되지 않습니다. 응답 지연에 매우 민감한 시스템의 경우 지연이 너무 많은 것과 서비스를 사용할 수 없는 것 사이에는 차이가 없습니다. 서비스를 사용할 수 없는 것보다 더 심각한 것은 스왑 시나리오에서 프로세스가 종료되지 않는다는 것입니다. 즉, 시스템을 항상 사용할 수 없음을 의미합니다. ...다시 생각해 보세요. 스왑을 사용하지 않고 직접 oom하는 것이 더 나은 선택일까요? 이런 식으로 많은 고가용성 시스템이 마스터와 슬레이브 간에 직접 전환되며 사용자는 기본적으로 이를 인식하지 못합니다.
2. 또한 HBase와 같은 분산 시스템의 경우 실제로 특정 노드가 다운되는 것을 걱정하지 않지만 특정 노드가 멈추는 것을 걱정합니다. 노드가 다운되면 최대 소수의 요청을 일시적으로 사용할 수 없으며 재시도를 통해 복구할 수 있습니다. 그러나 노드가 차단되면 모든 분산 요청이 차단되고 서버 측 스레드 리소스가 점유되어 전체 클러스터 요청이 차단되고 심지어 클러스터도 다운됩니다.
이 두 가지 관점에서 볼 때 모든 데이터베이스가 스왑을 좋아하지 않는 것이 합리적입니다!
스왑의 작동 메커니즘
데이터베이스는 스왑을 좋아하지 않기 때문에 디스크 캐시 기능을 끄려면 swapoff 명령을 사용해야 합니까? 아니요, 생각해 볼 수 있습니다. 디스크 캐시를 끄는 것은 무엇을 의미합니까? 실제 생산 환경의 어떤 시스템도 그렇게 급진적이지는 않습니다. 세상은 결코 0이나 1이 아니라는 것을 알아야 합니다. 모든 사람은 어느 정도 중간을 선택하지만 일부는 0에 편향되고 일부는 1에 편향됩니다. 분명히 스왑과 관련하여 데이터베이스는 스왑을 가능한 한 적게 사용하도록 선택해야 합니다. HBase 공식 문서의 몇 가지 요구 사항은 실제로 이 정책을 구현하기 위한 것입니다. 즉, 스왑의 영향을 최대한 줄입니다. 자신과 적을 알아야만 모든 전투에서 승리할 수 있습니다. 스왑의 영향을 줄이려면 가능한 의심을 놓치지 않도록 Linux 메모리 재활용이 어떻게 작동하는지 이해해야 합니다.
먼저 스왑이 어떻게 실행되는지 살펴볼까요?
간단히 말하면 Linux는 두 가지 시나리오로 메모리 재활용을 실행합니다. 하나는 메모리 할당 중에 여유 메모리가 충분하지 않은 것으로 확인되면 즉시 메모리 재활용이 실행된다는 것입니다. 프로세스) 주기가 시작됩니다. 시스템 메모리를 지속적으로 확인하고 사용 가능한 메모리가 특정 임계값으로 떨어지면 메모리 회수를 적극적으로 트리거합니다. 첫 번째 시나리오에 대해서는 말할 것도 없습니다. 아래 그림과 같이 두 번째 시나리오에 집중하겠습니다.
여기서 우리가 관심을 두는 첫 번째 매개변수인 vm.min_free_kbytes는 예약된 여유 메모리를 나타냅니다. 최소 워터마크[min]에 의해 결정되며 워터마크[낮음] 및 워터마크[높음]에 영향을 미칩니다. 이는 간단히 다음과 같이 생각할 수 있습니다:
watermark[min] = min_free_kbytes watermark[low] = watermark[min] * 5 / 4 = min_free_kbytes * 5 / 4 watermark[high] = watermark[min] * 3 / 2 = min_free_kbytes * 3 / 2 watermark[high] - watermark[low] = watermark[low] - watermark[min] = min_free_kbytes / 4
LInux의 이러한 수위는 min_free_kbytes 매개변수와 분리될 수 없다는 것을 알 수 있습니다. 시스템에 대한 min_free_kbytes의 중요성은 자명합니다. 너무 크거나 작을 수 없습니다.
min_free_kbytes가 너무 작으면 [min, low] 사이의 수위 버퍼가 매우 작아집니다. kswapd 재활용 프로세스 중에 상위 계층이 메모리에 너무 빠르게 적용되면(일반적인 응용 프로그램: 데이터베이스) 사용 가능한 메모리가 쉽게 감소합니다. 워터마크[min] 아래에서는 커널이 직접 회수를 수행하고 애플리케이션의 프로세스 컨텍스트에서 직접 회수한 다음 회수된 여유 페이지를 사용하여 메모리 요청을 충족하므로 실제로 애플리케이션을 차단하고 발생하는 문제가 발생합니다. 특정 응답 지연이 될 것입니다. 물론 min_free_kbytes가 너무 커서는 안 됩니다. 한편으로는 너무 크면 애플리케이션 프로세스의 메모리가 줄어들고 다른 한편으로는 kswapd 프로세스가 소모될 수도 있습니다. 메모리 재활용에 많은 시간을 할애합니다. 이 프로세스를 다시 살펴보세요. Java 가비지 수집 메커니즘의 CMS 알고리즘에 있는 이전 세대 재활용 트리거 메커니즘과 유사합니까? 매개변수 -XX:CMSInitiatingOccupancyFraction을 생각해 보세요. 공식 문서에서는 min_free_kbytes가 1G(대규모 메모리 시스템에서는 8G로 설정)보다 작을 수 없도록 요구합니다. 즉, 직접 재활용을 쉽게 트리거하지 마십시오.
지금까지 Linux의 메모리 재활용 트리거 메커니즘과 우리가 우려하는 첫 번째 매개 변수 vm.min_free_kbytes에 대해 기본적으로 설명했습니다. 다음으로, 리눅스 메모리 재활용이 무엇을 재활용하는지 간단히 살펴보겠습니다. Linux 메모리 재활용 개체는 주로 두 가지 유형으로 나뉩니다.
1. 파일 캐시는 이해하기 쉽습니다. 매번 하드 디스크에서 파일 데이터를 읽어야 하는 것을 피하기 위해 시스템은 핫스팟 데이터를 메모리에 저장합니다. 성능을 향상시키기 위해. 파일만 읽는 경우 메모리 재활용은 메모리의 이 부분만 해제하면 됩니다. 다음에 파일 데이터를 읽을 때 하드 디스크에서 직접 읽을 수 있습니다(HBase 파일 캐시와 유사). 파일을 읽어오는 것뿐만 아니라 캐시된 파일 데이터도 수정(더티 데이터)하는 경우 메모리를 재활용하려면 데이터 파일의 이 부분을 하드 디스크에 쓴 후 해제해야 합니다(MySQL 파일과 유사). 은닉처).
2. 익명 메모리, 일반적인 힙 및 스택 데이터와 같은 하드 디스크 파일과 같은 캐리어가 있는 파일 캐시와 달리 메모리의 이 부분에는 실제 캐리어가 없습니다. 메모리의 이 부분은 재활용 중에 파일과 같은 매체에 직접 해제되거나 다시 쓸 수 없습니다. 이것이 바로 이러한 유형의 메모리를 하드 디스크로 교체하고 필요할 때 다시 로드하기 위해 스왑 메커니즘이 개발된 이유입니다.
어떤 파일 캐시나 익명 메모리를 재활용해야 하는지 결정하기 위해 Linux에서 사용하는 특정 알고리즘은 여기서는 문제가 되지 않습니다. 관심이 있는 경우 여기를 참조하세요. 그러나 우리가 생각해 보아야 할 질문이 있습니다. 재활용할 수 있는 메모리에는 두 가지 유형이 있는데 두 유형의 메모리가 모두 재활용될 수 있을 때 Linux는 어떤 유형의 메모리를 재활용할지 어떻게 결정합니까? 아니면 둘 다 재활용되나요? 여기서 우리가 관심을 두는 두 번째 매개변수는 swappiness입니다. 이 값은 커널이 스왑을 얼마나 적극적으로 사용하는지 정의하는 데 사용됩니다. 값이 높을수록 커널은 스왑을 덜 사용하게 됩니다. 양성. 값의 범위는 0~100이고 기본값은 60입니다. 이러한 교환성은 어떻게 달성됩니까? 구체적인 원리는 매우 복잡합니다. 간단히 말해서, swappiness는 메모리 재활용 중에 더 많은 익명 페이지를 재활용할지 또는 더 많은 파일 캐시를 재활용할지 제어하여 이러한 효과를 얻습니다. swappiness는 100과 같으며 이는 익명 메모리와 파일 캐시가 동일한 우선순위로 재활용됨을 의미합니다. 기본값 60은 파일 캐시가 먼저 재활용되어야 함을 의미합니다. 생각해 보세요(파일 캐시를 재활용하는 일반적인 상황에서는 IO 작업이 발생하지 않으며 시스템 성능에 거의 영향을 미치지 않습니다). 데이터베이스의 경우 Swap은 최대한 피해야 하므로 0으로 설정해야 합니다. 0으로 설정한다고 해서 스왑이 실행되지 않는다는 의미는 아닙니다!
지금까지 Linux 메모리 재활용 트리거 메커니즘, Linux 메모리 재활용 개체 및 스왑에 대해 이야기하고 min_free_kbytes 및 swappiness 매개변수에 대해 설명했습니다. 다음으로 스왑과 관련된 또 다른 매개변수인 zone_reclaim_mode를 살펴보겠습니다. 문서에는 이 매개변수를 0으로 설정하면 NUMA의 영역 회수가 비활성화될 수 있다고 나와 있습니다. NUMA의 경우 데이터베이스는 다시는 만족하지 못합니다. 많은 DBA가 속임을 당했습니다. 여기에 세 가지 작은 질문이 있습니다. NUMA란 무엇입니까? NUMA와 스왑의 관계는 무엇입니까? zone_reclaim_mode의 구체적인 의미는 무엇입니까?
NUMA(Non-Uniform Memory Access)는 UMA와 관련이 있습니다. 둘 다 CPU 설계 아키텍처입니다. 초기 CPU는 아래 그림(인터넷에서 가져온 사진)과 같이 UMA 구조로 설계되었습니다. 동일한 메모리를 읽는 멀티 코어 CPU에서 발생하는 채널 병목 현상 문제를 완화하기 위해 칩 엔지니어는 아래 그림과 같이 NUMA 구조를 설계했습니다(인터넷 사진).
이 아키텍처는 문제를 잘 해결할 수 있습니다. 즉, 서로 다른 CPU에는 독점적인 메모리 영역이 있습니다. CPU 간에 "메모리 격리"를 달성하려면 소프트웨어 수준에서 두 가지 지원 지점이 필요합니다.
1. 内存分配需要在请求线程当前所处CPU的专属内存区域进行分配。如果分配到其他CPU专属内存区,势必隔离性会受到一定影响,并且跨越总线的内存访问性能必然会有一定程度降低。
2. 另外,一旦local内存(专属内存)不够用,优先淘汰local内存中的内存页,而不是去查看远程内存区是否会有空闲内存借用。
这样实现,隔离性确实好了,但问题也来了:NUMA这种特性可能会导致CPU内存使用不均衡,部分CPU专属内存不够使用,频繁需要回收,进而可能发生大量swap,系统响应延迟会严重抖动。而与此同时其他部分CPU专属内存可能都很空闲。这就会产生一种怪现象:使用free命令查看当前系统还有部分空闲物理内存,系统却不断发生swap,导致某些应用性能急剧下降。见叶金荣老师的MySQL案例分析:《找到MySQL服务器发生SWAP罪魁祸首》。
所以,对于小内存应用来讲,NUMA所带来的这种问题并不突出,相反,local内存所带来的性能提升相当可观。但是对于数据库这类内存大户来说,NUMA默认策略所带来的稳定性隐患是不可接受的。因此数据库们都强烈要求对NUMA的默认策略进行改进,有两个方面可以进行改进:
1. 将内存分配策略由默认的亲和模式改为interleave模式,即会将内存page打散分配到不同的CPU zone中。通过这种方式解决内存可能分布不均的问题,一定程度上缓解上述案例中的诡异问题。对于MongoDB来说,在启动的时候就会提示使用interleave内存分配策略:
WARNING: You are running on a NUMA machine. We suggest launching mongod like this to avoid performance problems: numactl –interleave=all mongod [other options]
2. 改进内存回收策略:此处终于请出今天的第三个主角参数zone_reclaim_mode,这个参数定义了NUMA架构下不同的内存回收策略,可以取值0/1/3/4,其中0表示在local内存不够用的情况下可以去其他的内存区域分配内存;1表示在local内存不够用的情况下本地先回收再分配;3表示本地回收尽可能先回收文件缓存对象;4表示本地回收优先使用swap回收匿名内存。可见,HBase推荐配置zone_reclaim_mode=0一定程度上降低了swap发生的概率。
不都是swap的事
至此,我们探讨了三个与swap相关的系统参数,并且围绕Linux系统内存分配、swap以及NUMA等知识点对这三个参数进行了深入解读。除此之外,对于数据库系统来说,还有两个非常重要的参数需要特别关注:
1. IO调度策略:这个话题网上有很多解释,在此并不打算详述,只给出结果。通常对于sata盘的OLTP数据库来说,deadline算法调度策略是最优的选择。
2. THP(transparent huge pages)特性关闭。THP特性笔者曾经疑惑过很久,主要疑惑点有两点,其一是THP和HugePage是不是一回事,其二是HBase为什么要求关闭THP。经过前前后后多次查阅相关文档,终于找到一些蛛丝马迹。这里分四个小点来解释THP特性:
(1)什么是HugePage?
网上对HugePage的解释有很多,大家可以检索阅读。简单来说,计算机内存是通过表映射(内存索引表)的方式进行内存寻址,目前系统内存以4KB为一个页,作为内存寻址的最小单元。随着内存不断增大,内存索引表的大小将会不断增大。一台256G内存的机器,如果使用4KB小页, 仅索引表大小就要4G左右。要知道这个索引表是必须装在内存的,而且是在CPU内存,太大就会发生大量miss,内存寻址性能就会下降。
HugePage就是为了解决这个问题,HugePage使用2MB大小的大页代替传统小页来管理内存,这样内存索引表大小就可以控制的很小,进而全部装在CPU内存,防止出现miss。
(2)什么是THP(Transparent Huge Pages)?
HugePage是一种大页理论,那具体怎么使用HugePage特性呢?目前系统提供了两种使用方式,其一称为Static Huge Pages,另一种就是Transparent Huge Pages。前者根据名称就可以知道是一种静态管理策略,需要用户自己根据系统内存大小手动配置大页个数,这样在系统启动的时候就会生成对应个数的大页,后续将不再改变。而Transparent Huge Pages是一种动态管理策略,它会在运行期动态分配大页给应用,并对这些大页进行管理,对用户来说完全透明,不需要进行任何配置。另外,目前THP只针对匿名内存区域。
(3)HBase(数据库)为什么要求关闭THP特性?
THP는 런타임 중에 큰 페이지를 할당하고 관리하는 동적 관리 전략이므로 응답 지연을 추구하는 데이터베이스 시스템에서는 허용되지 않는 어느 정도의 할당 지연이 발생합니다. 또한 THP에는 다른 많은 단점이 있습니다. "why-tokudb-hates-transparent-hugepages" 기사를 참조하세요.
(4) THP를 끄거나 켜는 것이 HBase의 읽기 및 쓰기 성능에 얼마나 많은 영향을 미치나요?
THP를 켜고 끄는 것이 HBase 성능에 미치는 영향을 확인하기 위해 테스트 환경에서 간단한 테스트를 수행했습니다. 테스트 클러스터에는 RegionServer가 하나만 있고 테스트 부하는 읽기-쓰기 비율이 1:1입니다. . THP에는 두 가지 옵션이 있습니다. 일부 시스템에서는 항상 및 절대 안 함, 일부 시스템에서는 madvise라는 추가 옵션이 있습니다. echo never/always > /sys/kernel/mm/transparent_hugepage/enabled 명령을 사용하여 THP를 켜거나 끌 수 있습니다. 테스트 결과는 아래 그림과 같습니다.
위 그림과 같이 TPH 종료 시나리오(never)에서 HBase가 가장 좋은 성능을 가지며 상대적으로 안정적입니다. THP가 켜져 있는 장면(항상)에서는 THP가 꺼진 장면에 비해 성능이 약 30% 정도 떨어지며, 곡선 지터가 크게 발생합니다. HBase에서 온라인으로 THP를 끄는 것을 기억하는 것을 볼 수 있습니다.
관련 추천: "Linux 비디오 튜토리얼"
위 내용은 리눅스 스왑이 뭐야?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!