당신이 이것에 대답하기 전에 나는 서버로드를 높이기에 충분한 인기있는 것을 개발하지 않았습니다. PHP와 몇 가지 최적화 기술을 알고 있지만 지구상에서 방금 착륙 한 외계인으로 나를 처리하십시오.
제대로 작동하면 꽤 많은 사용자를 확보 할 수 있는 PHP 도구를 개발 중입니다. 그러나 프로그램을 완전히 개발할 수는 있지만 엄청난 트래픽을 처리 할 수있는 무언가를 만드는 데는 실마리가 거의 없습니다. 여기에 몇 가지 질문이 있습니다 (이 질문을 리소스 스레드로 자유롭게 전환하십시오).
데이터베이스
현재 PHP5에서 MySQLi 기능을 사용할 계획입니다. 그러나 사용자 및 컨텐츠와 관련하여 데이터베이스를 어떻게 설정해야합니까? 실제로 여러 데이터베이스 가 필요 합니까? 현재 모든 것이 하나의 데이터베이스로 뒤죽박죽되었습니다. 사용자 데이터를 하나의 실제 콘텐츠로 다른 것으로, 마지막으로 핵심 사이트 콘텐츠 (템플릿 마스터 등)를 다른 데이터베이스로 확산시키는 것을 고려하고 있었지만. 이것에 대한 나의 추론은 다른 데이터베이스에 쿼리를 보내면 하나의 데이터베이스 = 3로드 소스로 데이터베이스에 대한로드를 완화한다는 것입니다. 모두 동일한 서버에있는 경우에도 여전히 효과적입니까?
캐싱
페이지를 작성하고 변수를 교체하는 데 사용되는 템플릿 시스템이 있습니다. 마스터 템플릿은 데이터베이스에 저장되며 템플릿을 호출 할 때마다 캐시 된 사본 (html 문서)이 호출됩니다. 현재이 템플릿에는 두 가지 유형의 변수 인 정적 변수와 동적 변수가 있습니다. 정적 변수는 일반적으로 페이지 이름, 사이트 이름, 자주 변경되지 않는 것입니다. 동적 변수는 각 페이지로드에서 변경되는 것입니다.
이것에 대한 내 질문 :
다른 기사에 대한 의견이 있다고 가정 해보십시오. 더 나은 해결책은 페이지를로드 할 때마다 간단한 주석 템플릿을 저장하고 (DB 호출에서) 주석을 렌더링하거나 주석 페이지의 캐시 된 사본을 HTML 페이지로 저장하는 것입니다-주석이 추가 / 편집 / 삭제 될 때마다 페이지가 다시 캐시됩니다.
드디어
PHP에서 고부하 사이트를 운영하기위한 팁 / 포인터가 있습니까? 사용 가능한 언어 인 것이 확실합니다-Facebook 및 Yahoo! 우선 순위를 높이십시오.하지만주의해야 할 경험이 있습니까?
답변
두 사이트가 비슷하지 않습니다. 문제 지점이 어디 있는지 확인 하려면 jmeter 및 벤치 마크와 같은 도구가 필요 합니다. 추측하고 개선하는 데 많은 시간을 할애 할 수 있지만 변경 사항을 측정하고 비교할 때까지 실제 결과는 표시되지 않습니다.
예를 들어, 수년 동안 MySQL 쿼리 캐시는 모든 성능 문제에 대한 솔루션이었습니다. 사이트 속도가 느리면 MySQL 전문가가 쿼리 캐시를 켤 것을 제안합니다. 쓰기로드가 높으면 실제로 캐시가 손상되고있는 것으로 나타났습니다. 테스트하지 않고 전원을 켜면 알 수 없습니다.
그리고 스케일링이 완료된 것을 잊지 마십시오. 10req / s를 처리하는 사이트는 1000req / s를 지원하도록 변경해야합니다. 10,000req / s를 지원할만큼 운이 좋으면 아키텍처도 완전히 다르게 보일 것입니다.
데이터베이스
- MySQLi를 사용하지 마십시오 – PDO가 ‘현대’OO 데이터베이스 액세스 레이어입니다. 가장 중요한 기능은 쿼리에서 자리 표시 자입니다. 서버 측 준비 및 기타 최적화 기능을 사용하는 것이 현명합니다.
- 이 시점에서 데이터베이스를 분리하고 싶지 않을 것입니다. 하나의 데이터베이스가 잘리지 않는 경우 앱에 따라 몇 가지 기술을 확장 할 수 있습니다. 쓰기보다 읽기가 많은 경우 일반적으로 추가 서버로 복제하는 것이 좋습니다. 샤딩은 여러 머신에서 데이터를 분할하는 기술입니다.
캐싱
- 데이터베이스에 캐시하고 싶지 않을 것입니다. 데이터베이스는 일반적으로 병목 현상이므로 IO를 더 추가하는 것은 일반적으로 나쁜 일입니다. APC 및 Zend와 유사한 기능을 수행하는 몇 가지 PHP 캐시가 있습니다 .
- 캐싱을 켜고 끈 상태에서 시스템을 측정하십시오. 캐시가 페이지를 똑바로 제공하는 것보다 무겁습니다.
- db에서 주석 및 기사 데이터를 작성하는 데 시간이 오래 걸리면 memcache 를 시스템에 통합 하십시오. 쿼리 결과를 캐시하여 memcached 인스턴스에 저장할 수 있습니다. memcache에서 데이터를 검색하는 것이 데이터베이스에서 데이터를 조합하는 것보다 빠르다는 점을 기억해야합니다.
- 기사가 동적이 아니거나 생성 된 후 간단한 동적 변경이있는 경우 디스크에 html 또는 php를 작성하는 것이 좋습니다. 디스크에서 기사를 찾는 index.php 페이지가있을 수 있으며, 있다면 기사를 클라이언트로 스트리밍합니다. 그렇지 않은 경우 기사를 생성하고 디스크에 쓴 다음 클라이언트로 보냅니다. 디스크에서 파일을 삭제하면 페이지가 다시 작성됩니다. 기사에 주석이 추가 된 경우 캐시 된 사본을 삭제하면 주석이 다시 생성됩니다.
답변
저는 1 억 5 천만 명의 사용자가있는 사이트의 수석 개발자입니다. 우리는 초기에 계획하고 신중하게 확장했기 때문에 확장 문제가 거의 없었습니다. 다음은 내 경험에서 제안 할 수있는 몇 가지 전략입니다.
SCHEMA
먼저 스키마를 비정규 화하십시오. 즉, 여러 관계형 테이블을 갖는 대신 하나의 큰 테이블을 선택해야합니다. 일반적으로 조인은 여러 준비 및 데이터 정렬을 수행하면 디스크 I / O가 손상되므로 귀중한 DB 리소스가 낭비됩니다. 가능하면 피하십시오.
여기서 중복되는 데이터는 중복 데이터를 저장 / 풀링한다는 것입니다. 그러나 데이터 및 케이지 내부 대역폭이 매우 저렴하고 (더 큰 디스크) 다중 준비 I / O가 훨씬 비싸기 때문에 (서버가 더 많기 때문에) 이는 수용 가능합니다. .
인덱싱
쿼리가 적어도 하나의 인덱스를 사용하는지 확인합니다. 그러나 자주 쓰거나 업데이트하면 색인 비용이 발생합니다. 이를 피하기위한 몇 가지 실험적인 트릭이 있습니다.
인덱싱되지 않은 열을 인덱싱 된 열과 병렬로 추가하여 추가 할 수 있습니다. 그런 다음 인덱싱되지 않은 열을 인덱싱 된 열에 일괄 적으로 쓰는 오프라인 프로세스를 가질 수 있습니다. 이런 식으로 mySQL이 인덱스를 다시 계산해야 할 때 더 잘 제어 할 수 있습니다.
전염병과 같은 계산 쿼리를 피하십시오. 쿼리를 계산해야하는 경우 쓰기시 한 번 수행하십시오.
CACHING
나는 매우 memcached를하는 것이 좋습니다. PHP 스택 (Facebook)에서 가장 큰 플레이어에 의해 입증되었으며 매우 유연합니다. 이를 수행하는 두 가지 방법이 있습니다. 하나는 DB 계층에서 캐싱하고 다른 하나는 비즈니스 로직 계층에서 캐싱입니다.
DB 계층 옵션을 사용하려면 DB에서 검색 한 쿼리 결과를 캐싱해야합니다. md5 ()를 사용하여 SQL 쿼리를 해시하고 데이터베이스로 이동하기 전에이를 조회 키로 사용할 수 있습니다. 이것의 단점은 구현하기가 쉽다는 것입니다. 단점 (구현에 따라 다름)은 캐시 만료와 관련하여 모든 캐싱을 동일하게 취급하기 때문에 유연성이 떨어집니다.
내가 작업하는 상점에서는 비즈니스 계층 캐싱을 사용합니다. 즉, 시스템의 각 콘크리트 클래스가 자체 캐싱 스키마 및 캐시 시간 초과를 제어합니다. 이것은 우리에게는 꽤 효과가 있었지만 DB에서 검색 한 항목은 캐시의 항목과 같지 않을 수 있으므로 캐시와 DB를 함께 업데이트해야합니다.
데이터 보호
복제는 지금까지만 가능합니다. 예상보다 빨리 쓰기 작업에 병목 현상이 발생합니다. 이를 보완하려면 가능한 빨리 데이터 샤딩을 지원해야합니다. 당신이하지 않으면 나중에 자신을 촬영하고 싶을 것입니다.
구현하는 것은 매우 간단합니다. 기본적으로 데이터 저장소에서 키 권한을 분리하려고합니다. 기본 DB와 클러스터 ID 간의 매핑을 저장하려면 글로벌 DB를 사용하십시오. 이 매핑을 쿼리하여 클러스터를 얻은 다음 클러스터를 쿼리하여 데이터를 가져옵니다. 이 조회 작업에서 지옥을 캐시하여 무시할 수있는 작업으로 만들 수 있습니다.
이것의 단점은 여러 샤드의 데이터를 함께 수집하기가 어렵다는 것입니다. 그러나, 당신은 그것의 주위에 길을 엔지니어링 할 수 있습니다.
오프라인 처리
사용자가 백엔드를 기다리지 않아도되도록 기다리지 마십시오. 작업 큐를 작성하고 오프라인으로 처리 할 수있는 모든 처리를 사용자 요청과 별도로 수행하십시오.
답변
PHP 및 MySQL의 지원을받는 수백만 / 히트 / 월을 얻는 소수의 사이트에서 일했습니다. 기본 사항은 다음과 같습니다.
- 캐시, 캐시, 캐시. 캐싱은 웹 서버 및 데이터베이스의 부하를 줄이는 가장 간단하고 효과적인 방법 중 하나입니다. 캐시 된 페이지 내용, 쿼리, 비싼 계산, I / O 바인딩 된 모든 것. Memcache는 간단하고 효과적입니다.
- 최대 한도에 도달하면 여러 서버를 사용하십시오. 여러 웹 서버와 여러 데이터베이스 서버 (복제 포함)를 가질 수 있습니다.
- 웹 서버에 대한 전체 요청 수를 줄입니다. 이 경우 Expirs 헤더를 사용하여 JS, CSS 및 이미지를 캐싱해야합니다. 정적 컨텐츠를 CDN으로 이동하여 사용자 경험을 향상시킬 수 있습니다.
- 측정 및 벤치 마크. 프로덕션 머신에서 Nagios를 실행하고 dev / qa 서버에서로드 테스트하십시오. 서버가 불을 붙일 때를 알아야이를 방지 할 수 있습니다.
확장 가능한 웹 사이트 구축을 읽는 것이 좋습니다 . Flickr 엔지니어 중 한 사람이 작성했으며 훌륭한 참고 자료입니다.
확장성에 대한 내 블로그 게시물을 확인하십시오. 여러 언어 및 플랫폼으로 확장하는 방법에 대한 프레젠테이션 링크가 많이 있습니다.
http://www.ryandoherty.net/2008/07/13/unicorns-and-scalability/
답변
재 : PDO / MySQLi / MySQLND
@ 게리
목표가 다르기 때문에 “MySQLi를 사용하지 마십시오”라고 말할 수는 없습니다. PDO는 추상화 계층과 거의 비슷하지만 실제로는 아니지만 여러 데이터베이스 제품을 쉽게 사용할 수 있도록 설계되었지만 MySQLi는 MySQL 연결에만 적용됩니다. PDO가 MySQLi와 비교하는 맥락에서 PDO가 최신 액세스 계층이라고 말하는 것은 잘못된 일입니다.
MySQLi와 PDO 사이의 선택은 간단합니다. 여러 데이터베이스 제품을 지원해야하는 경우 PDO를 사용하십시오. MySQL 만 사용하는 경우 PDO와 MySQLi 중에서 선택할 수 있습니다.
그렇다면 왜 PDO 대신 MySQLi를 선택하겠습니까? 아래를 참조하십시오 …
최신 MySQL 핵심 언어 레벨 라이브러리 인 MySQLnd에 대해서는 정확하지만 MySQLi를 대체하지는 않습니다. PDO와 마찬가지로 MySQLi는 PHP 코드를 통해 MySQL과 상호 작용하는 방식으로 남아 있습니다. 이 두 가지 모두 libmysql을 PHP 코드의 C 클라이언트로 사용합니다. 문제는 libmysql이 핵심 PHP 엔진 외부에 있으며 mysqlnd가있는 곳입니다. 즉, 효율성을 극대화하기 위해 핵심 PHP 내부를 사용하는 네이티브 드라이버, 특히 메모리 사용과 관련이 있습니다.
MySQLnd는 MySQL 자체에서 개발하고 있으며 최근에는 RC 테스트중인 PHP 5.3 브랜치에 착륙하여 올해 후반에 출시 될 예정입니다. 그러면 Pnd가 아닌 MySQLi에서 MySQLnd를 사용할 수 있습니다. 이것은 많은 영역에서 MySQLi 의 성능 향상 을 가져다 줄 것이며 PDO의 기능과 같은 추상화가 필요하지 않은 경우 MySQL 상호 작용을위한 최상의 선택이 될 것입니다.
즉, MySQLnd 는 이제 PDO 용 PHP 5.3에서 사용할 수 있으므로 ND에서 PDO로 성능 향상의 이점을 얻을 수 있지만 PDO는 여전히 일반적인 데이터베이스 계층이므로 다음과 같은 이점을 얻을 수 없을 것입니다. MySQLi가 할 수있는 것처럼 ND의 향상된 기능 .
유용한 벤치 마크는 2006 년부터 있지만 여기에서 확인할 수 있습니다 . 이 옵션 과 같은 사항도 알고 있어야 합니다.
MySQLi와 PDO 사이를 결정할 때 고려해야 할 사항이 많이 있습니다. 현실적으로 당신이 엄청나게 많은 요청 수에 도달 할 때까지는 중요하지 않으며,이 경우 사물을 추상화하고 MySQL 드라이버를 제공하는 것보다 MySQL 용으로 특별히 설계된 확장을 사용하는 것이 더 합리적입니다 .
각각의 장점과 단점이 있기 때문에 가장 간단한 문제는 아닙니다. 내가 제공 한 링크를 읽고 자신의 결정을 내린 다음 테스트하고 알아 내야합니다. 나는 과거 프로젝트에서 PDO를 사용했으며 좋은 확장이지만 순수한 성능을 위해 선택하는 것은 새로운 MySQLND 옵션이 컴파일 된 MySQLi입니다 (PHP 5.3이 출시 될 때).
답변
일반
- 실제 하중을보기 전에 최적화하지 마십시오. 당신은 맞을지 모르지만, 그렇지 않으면 시간을 낭비한 것입니다.
- 사용 JMeter를 , Xdebug는 또는 벤치 마크에 다른 도구 사이트.
- 로드가 문제가되기 시작하면 객체 또는 데이터 캐싱이 관련 될 가능성이 있으므로 일반적으로 캐싱 옵션 (memcached, MySQL 캐싱 옵션)을 읽으십시오.
암호
- 병목 현상의 위치와 코드 또는 데이터베이스에 있는지 여부를 알 수 있도록 코드를 프로파일 링하십시오.
데이터베이스
- 다른 데이터베이스로의 이식성이 중요하지 않은 경우 MYSQLi를 사용하고 , 그렇지 않으면 PDO
- 벤치 마크에서 데이터베이스에 문제가있는 것으로 나타나면 캐싱을 시작하기 전에 쿼리를 확인하십시오. EXPLAIN 을 사용 하여 쿼리 속도가 저하되는 위치를 확인하십시오.
- 쿼리가 최적화되고 데이터베이스가 어떤 식 으로든 캐시 된 후 여러 데이터베이스를 사용할 수 있습니다. 데이터, 쿼리 및 읽기 / 쓰기 동작의 종류에 따라 여러 서버로 복제하거나 샤딩 (여러 데이터베이스 / 서버로 데이터를 분할)이 적절할 수 있습니다.
캐싱
- 코드, 객체 및 데이터 캐싱에 대한 많은 작성이 이루어졌습니다. APC , Zend Optimizer , memcached , QuickCache 에 관한 기사를 찾아보십시오 , JPCache 찾아보십시오 . 실제로 필요한 작업을 수행하기 전에이 작업을 수행하면 최적화되지 않은 상태에서 시작하는 것에 대해 덜 걱정할 것입니다.
- APC와 Zend Optimizer는 opcode 캐시이며 코드 재분석 및 재 컴파일을 피하여 PHP 코드 속도를 높입니다. 일반적으로 설치가 간단하고 조기에 가치가 있습니다.
- Memcached는 일반 캐시로, 쿼리, PHP 함수 또는 객체 또는 전체 페이지를 캐시하는 데 사용할 수 있습니다. 캐시 된 객체의 생성, 업데이트 및 삭제를 처리 할 중앙 지점이없는 경우 관련 프로세스가 될 수있는 코드를 사용하려면 코드를 특별히 작성해야합니다.
- QuickCache 및 JPCache는 파일 캐시이며, 그렇지 않으면 Memcached와 유사합니다. 기본 개념은 간단하지만 코드가 필요하며 중앙에서 생성, 업데이트 및 삭제 지점이 있으면 더 쉽습니다.
여러 가지 잡다한
답변
APC 는 절대적으로 필요합니다. 그것은 훌륭한 캐싱 시스템을 만들뿐만 아니라 자동 캐시 된 PHP 파일의 이점은 신의 선물입니다. 다중 데이터베이스 아이디어에 관해서는 동일한 서버에서 다른 데이터베이스를 사용하는 데 많은 도움이 될 것이라고 생각하지 않습니다. 쿼리 시간 동안 약간의 속도 향상을 가져올 수 있지만, 세 가지 코드를 모두 배포하고 유지하면서 코드를 동기화하고 유지하는 것이 가치가 있다고 생각합니다.
또한 프로그램에서 병목 현상을 찾기 위해 Xdebug 를 실행하는 것이 좋습니다 . 그것은 나를 위해 최적화를 산들 바람으로 만들었습니다.
답변
먼저 Knuth가 말한 것처럼 “조기 최적화는 모든 악의 근원”입니다. 지금 당장 이러한 문제를 처리 할 필요가 없다면, 올바르게 작동하지 않는 것을 제공하는 데 집중하십시오. 최적화가 기다릴 수 없다면 말입니다.
데이터베이스 쿼리를 프로파일 링하고 느리게 진행되는 작업과 발생하는 작업을 파악한 후 그로부터 최적화 전략을 수립하십시오.
Memcached 는 모든 유형의 컨텐츠를 효율적으로 캐싱하기 위해 많은 고부하 사이트가 사용하는 것으로 Memcached 를 조사 할 것이며 이에 대한 PHP 객체 인터페이스는 매우 좋습니다.
서버간에 데이터베이스를 분할하고 일종의로드 밸런싱 기술을 사용하는 경우 (예 : 필요한 데이터로 중복 데이터베이스 1 개와 # 개 사이의 임의의 숫자 생성-이 숫자를 사용하여 연결할 데이터베이스 서버 결정)는 훌륭한 방법입니다. 능률.
이것들은 과거에 상당히 높은로드 사이트에 대해 잘 작동했습니다. 희망이 당신이 시작하는 데 도움이되기를 바랍니다 🙂