PHP용 redis query cache (쿼리 캐시) class

시간이 오래걸리는 쿼리의 결과 데이타를 캐시 처리하도록 만들어진 클래스입니다.

 

Facebook Comments

redis + phpredis 설치 및 php 에서 redis 사용방법

 

1. redis(레디스)가 뭔가요? 많이 들어는 봤는데…..

레디스(REmote DIctionary Server) 는 메모리기반 key-value store(저장소) 입니다. 

redis 는 주로 두가지 용도로 많이 습니다.

1. 데이타(또는 페이지) 캐시

2. 세션 저장소 

세션 저장소로 사용할 경우 대용량 분산처리가 가능하며, 서브도메인 세션공유를 쉽게 처리할수 있습니다.

2. redis 설치 및 시작

   2.1 centos6.x 에서 redis 설치 (centos7 도 동일)

 

  2.2 ubuntu 에서 설치

 

 

3. phpredis 설치

PHP 에서 redis 를 사용하기 위해서는 phpredis 라는 php 모듈이 필요합니다. 모듈을 컴파일해서 설치해야합니다. 어렵지 않음으로 순서만 잘 이해하면 됩니다.

먼저 php설치정보를 확인해야 합니다. php -i  나 웹페이지에서 phpinfo() 를 확인합니다.

화면에서 php.ini 의 설치위치를 잘봐둡니다. 제 서버는 /usr/local/php/etc/php.ini 에 위치하고 있네요.

phpredis 를 다운받아 컴파일 해야 합니다. 컴파일 순서는 아래와 같습니다.

  1. phpredis 최신 버전을 다운받습니다. git 을 통해 받거나, wget 으로 받으시면 됩니다.
  2. 다운받은 파일을 압축을 해제한다음, 디렉토리로 이동합니다.
  3. phpize 를 실행해줍니다. phpize 를 찾이못한다면, 풀경로로 실행합니다.
  4. configure 를 실행합니다. 이때 php 가 설치된 php-config 정보를 넣어줍니다.
  5. make, make install 을 실행해줍니다.

 

위에서 make install 후 출력되는 경로를 잘 확인해두어야 합니다. 나중에  php.ini 에 추가할 예정

 /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/

php.ini 파일을 수정해 주어야 합니다. php.ini 파일 위치는 아까 phpinfo()에서 확인하였습니다. php.ini 파일을 열어서 마지막에 아래 라인을 추가해줍니다. 저장후 php-fpm 을 재시작하고 다시 phpinfo()를 보시면 php에 redis 모듈이 표시되는걸 확인할수 있습니다. 세션 정보도 redis 로 변경합니다.

[redis]
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/redis.so
session.save_handler = redis
session.save_path = “tcp://127.0.0.1:6379”

 

4. 마지막으로 php로 redis 테스트

 

해당 소스를 저장후 웹페이지서 테스트를 하면, 처음 value가 없다가 새로고침 할때마다 1씩 증가합니다. 3초간 기다렸다가 다시 새로고침하면, 초기화 되는걸 볼수 있습니다.

phpredis 의 자세한 사용법은 https://github.com/phpredis/phpredis  를 참고하세요.
 
 

5. 끝으로..

그누보드5 (영카트) 에서 사용할때 주의점

그누보드5의 common.php 에는 session 설정과 관련된 코드가 들어 있습니다. redis 를 session 저장소로 사용하는 경우 session.save_path 를 수정하면 안됩니다.  /common.php 파일 190번 라인에 있는 아래 코드를 주석 처리 합니다.

//session_save_path(G5_SESSION_PATH);

 

 

참고자료

 

 

Facebook Comments

MySQL 쿼리 모니터링 팁

웹사이트가 느려지거나, 랙이 발생하게 되면 보통 DB를 모니터링합니다. 뭐 대부분 db 에서 문제가 발생하기 마련입니다.

slow 로그를 우선 모니터링 하게 되는데, 쿼리가 실행되는 페이지나 상황이 특정되는 경우는 쿼리를 튜닝하고, 해당 페이지의 서비스 코드(예를 들어 .php 파일)의 쿼리부분을 수정하면 쉽게 장애조치가 가능합니다.

그러나 웹페이지에서 쿼리에 변수 몇개를 바인드하여  사용하기 때문에, 쿼리로는 페이지나 상황을  특정하기 여러운 경우가 있습니다. 이런 경우에 사용할수 있는 간단한 팁입니다.

MySQL은 쿼리에 주석을 추가할수 있는데, 주석에 페이지 정보나 라인을 추가합니다. (이해를 하기 쉽게 하기 위해 그누보드5를 기준으로 설명하겠습니다.)

최근 게시물이나 게시물 수를  표시하기 위해 아래와 같은 쿼리가 들어간 페이지가 있습니다.

$sql = “select count(*) from g5_board_new where …..   “;

$sql = “select * from g5_board new where …. limit 5… “;

해당 쿼리가 들어간 php 파일은 찾았는데 파일수가 20개 라면,어떤 php 가 호출될때가 문제인지를 찾아야 합니다.

이때 다음과 같이 쿼리문에 주석을 추가합니다.

$sql = “select /*  “.$_SERVER[‘SCRIPT_NAME’].” */ from g5_board_new where … “;

$sql = “select /* “.$_SERVER[‘SCRIPT_NAME’].” */ * from g5_board new where …. limit 5… “;

(주석 위치는 가능한 공간이면 아무곳에 넣어도 상관없습니다.)

이제 이렇게 소스를 수정한뒤에 슬로우 쿼리를 보면, 문제가 되는 페이지를 찾을수 있습니다. 쿼리 튜닝이 어려운 페이지인 경우에는 캐시 처리를 하면 끝.

 

 

Facebook Comments

웹페이지 트래픽을 줄이는 5가지 방법

트래픽 = 돈  입니다.(특히 한국은 트래픽 비용이 외국보다 비쌉니다.)
트래픽만 줄여도 비용이 많이 save 됩니다.
cdn 을 클라우드플레어 쓴다면 트래픽 걱정이 많이 줄어들지만, 속도저하를 감수해야죠.
(클라우드 플레어의 플랜에 따른 colo 문제 때문에 커뮤니티에선 그럭저걸 쓸수 있지만, 쇼핑몰같은 비지니스 사이트에선 사용 불가)

비싼 idc 비용을 절감하기 위해 트래픽을 낮추는 방법입니다.

  1. lazy loading

    • 모든 상품 이미지는 lazy loading을 적용합니다. 썸네일포함
  2. 동적 썸네일 적용

    • 거의 모든 쇼핑몰 솔루션과 웹페이지들이 고정사이즈 썸네일 생성 방식을 사용합니다. 이미지가 업로드될때 썸네일을 사이즈별로 미리 생성하는 방식인데, 사이즈가 fix 된 상태임으로 다른 크기의 썸네일을 생성할때, 미리 생성된 크기중 비슷한걸 가져다가 쓰게 됩니다. 사이즈가 다른 이미지를 표시하는 경우 화질이 저하되어(블러효과) 표시되는 문제도 발생합니다.
    • 영카트를 예를 들어 설명드리면, 솔루션 특성상 s, m, l 이미지 3개만유지하는데,  썸네일은 페이지별로 상황에 따라 요청하는 크기가 다릅니다. 45×45 같은 작은 이미지를 150×130 으로 요청할 필요가 없는거죠.(별차이 없어보이지만, 작은 차이가 모이면 커집니다.)
  3. 퀵뷰(미리보기) 적용

    • 상품 상세 페이지나 갤러리 상세페이지에는  큰 원본 이미지가 있기 마련입니다. 가장 많은 트래픽을 만들어 냅니다.  가급적 사용자가 꼭 보고 싶은 상품이나, 사진만을 조회하도록 해야 합니다.
    • 사용자는 사실 상세페이지를 이동할때 발생하는 페이지 새로고침이 별로 좋아하지 않습니다.
    • 퀵뷰(미리보기)를 제공함으로써 상세 페이지 요청이 줄어들게 되고, 퀵뷰에는 2번의 동적썸네일을 표시하여 2중으로 트래픽을 절감할수 있습니다.
  4. 정적 데이타 캐싱

    • php나 java에서  thumbnail 같이 요청마다 이미지 트래픽을 만드는 동적페이지는 사용하지 않습니다. 워터마크를 넣는 작업때문에 이렇게 하시는 경우가 있는데, 지양하도록 합니다.
    • 이미지를 포함하여, 모든 정적 데이타는 캐싱이 되어야  합니다. nginx나 apache 설정에서 정적 데이타 처리가  빠져있다면 꼭 넣어줍니다.
  5. 캐싱 주기를 늘리자

    • 보통 업로드되는 이미지나 상품 상세사진들은 한번 올리면 변경되지 않습니다. 갤러리의 상세 이미지는 캐싱주기를 1일 이상 유지해도 됩니다.
    • 단 수정이 일어날수 있음으로 퍼지 기능을 추가하면 좋습니다. 보통 파일을 삭제함으로써 퍼지를 달성할수 있으나, cdn 을 사용하는 경우는 cdn의 퍼지 기능을 호출해줘야 하는 번거로움이 있습니다. 수정이 자주일어나는 경우라면 캐싱주기를 좀더 줄여줍니다.

위의 5가지를 적용하면, 트래픽이 많은  쇼핑몰 사이트의 경우 30~ 50% 이상 트래픽을 절감할수 있습니다.

Facebook Comments

더 나은 MySQL 성능을 위한 7가지 방법

원문보기

1. EXPLAIN 의 사용법을 배워라. 
– 슬로우 쿼리나, 사이트가 느려질때 processlist에 잔뜩 떠 있는 쿼리,  processlist 에 1초 이상 실행되는걸로 자주 보이는 쿼리가 있다면,
– explain 으로 쿼리의 index 와 실행형태를 보셔야 합니다.  적어도 쿼리가 index를 제대로 사용했는지는 볼수 있어야 합니다.

2. 제대로된 index를 생성하라 
– 1번에서 주로 문제가 되는건 index를 잘못 생성했거나, 너무 많이 생성한 경우입니다.
– index 는 많아도 문제가 됩니다. index가 많은 경우에 오히려 느려지는 경우도 있습니다.(대표적으로 merged intersection)

3.  디폴트값을 쓰지마라. 
– 이건 mysql 튜닝과 관련된 부분입니다. mysql 서버를 처음 설치하게 되면 my.cnf 가 디폴트값으로 들어갑니다.
디폴트값은 장비의 성능을 고려하여 책정된게 아닙니다. 특히 메모리와 버퍼 메모리에 관련된값은 시스템의 메모리를 고려하여 적정값으로 설정하여야 합니다. 적정값을 찾는데는 mysqltunner 가 도움이 될수 있습니다.

4. 가능한 메모리에 db를 유지하라 
– mysql은 데이타를 가능한 memory 에 로딩하여 처리합니다. innodb는 innodb_buffer_pool 에 설정된 크기만큼 메모리를 할당하여 로딩을 해둡니다. 이 값이 작으면, 디스크에서 메모리로 로딩하는 경우가 많아짐으로 성능이 저하되게 됩니다.
가급적 데이타베이스용량만큼은 설정되는게 좋습니다.(자주 안쓰는 테이블의 경우는 계산에서 빼도 됩니다.)
– db의 용량보다 메모리가 부족하다면 증설하는것도 고려해볼만합니다.
– 참고로 innodb_buffer_pool 외에도 버퍼를 많이 사용함으로 innodb_buffer_pool 은 현재 가용 메모리의 50~60%로 잡는게 좋습니다.)

5. SSD 를 사용하라 
– 당연한 애기지만, mysql은 disk read/write 가 많습니다. 4에서 메모리가 충분하더라도 로그를 기록하거나 bin 파일에 대한 write/purge 를 수행하게 됨으로 디스크속도가 느린경우 해당 잡이 실행될때 전체적인 성능저하가 일어납니다. 요즘은 mysql엔 대부분 ssd를 사용합니다.
–  mysql 은 장비 투자 순서는  memory > disk(ssd가 아니라면) > cpu(멀티코어보다는 cpu 클럭이 우선) 입니다.

6.  Scale out 
– 5번에서 하드웨어 성능을 더 이상 높힐수 없는 경우에, mysql을 스케일아웃 할수 있습니다.
– 여러가지 복잡한 방법들이 많지만, 가장 쉽게 스케일할수 있는 방법은 master /slave 방식입니다.
– 실행시간이 오래걸리는 배치잡이나 통계관련 쿼리, 관리자 페이지 select 쿼리들은 slave에서 요청하고
master 에서는 사용자 페이지 쿼리를 수행하게 합니다. 이렇게만 해도 피크시간대 db가 느려지는 문제를 많이 해결할수 있습니다.
– 게다가 슬레이브는 2대 3대로 늘릴수 있습니다.

7. 모니터링을 해라 
– mysql 모니터링 툴은 mysql 엔터프라즈 모니터링(유료), monyog(유료) 기타 다른 버전들 모두 유료입니다. pecona 툴은 무료인가 보네요.
– 국내 업체 whatap.io 에서 mysql 모니터링을 한달 5천(1만원인가) 사용할수 있습니다만, 어짜피 유료입니다.
– 유료툴이 아니더라도  mysql slow log만 잘 관찰하고 튜닝하더라도 많은 문제를 조기에 해결할수 있습니다.

Facebook Comments

SQL_INJECTION(SQL 인젝션)은 어떻게 막아야 하나요?

SQL_INJECTION(SQL 인젝션)은 어떻게 막아야 하나요?

1. pdo의 bind parameter,  pdo의 quota 함수,  mysql_real_eacape_string 함수 등을 이용 
– pdo  bind 를 쓰는게 가장 바람직합니다. 그냥 bind는 의미 없구요. order by 구문은 bind가 안되는 부분임으로
코드에서 order by value 를 꼭 확인해야 합니다. url 에 온 파라메타 그대로 order by에 쓰면 안돼요!!

2. url 파라메타에 select, update, union, and, or 구문 사용금지(그외 웹용 특수문자 입력금지) 
– 게시판은 이게 좀 곤란하죠… 게시판의 제목과, 본문, 코멘트는 그누보드 필터 함수를 꼭 쓰셔야 해요.(그누보드 함수 좋아요)

3. 웹서버에 웹방화벽 모듈 설치 mod_security or webknight, naxsi, dot depeder 등등.. 
– sql injection 공격이 한번 들어온곳은 계속 들어옴으로, 웹방화벽에서 추가를 해야 해요.. 개인적으로 nginx 모듈인 naxsi 를 추천합니다. 이건 다시한번 정리해서 올릴 예정입니다.

4. 웹방화벽 기능이 있는 cdn 서비스 이용 (클라우드 플레어 등) 
– 클라우드 플레어의 프로 플랜 이상이면 사용이 가능합니다. 정상적인걸 막는 경우도 있음으로 룰셋을 잘 관리해야 합니다.
(그런데 클라우드플레어 국내에선 너무 느려서…. 공격들어올때 잠깐 켰다가 끄는 방법을 추천)

5.웹소스로 된 방화벽 솔루션이나 코드 추가

– kisa 캐슬.. 성능은 예전에 안 좋았는데, 요즘은 어떤지 모르겠음.). github 에도 좀 있을듯.
– 경험삼아 한번씩 설치해보세요. 접속자가 많지 않은곳은 성능 이슈가 없어서 괜찮습니다.

 

지금 사이트와 개발자 상황에 맞춰서 5가지중에 가능한걸 적용하시면 됩니다.(2개 이상 적용하면 더 좋습니다.)

아래 예제는 php에서 sql injection 을 체크하기 위한 코드입니다. 간단해보이지만 효과적입니다.

 

 

Facebook Comments

블로그 설치 완료

블로그 개설했습니다.

개발 코드에 대한 공유와 개발 일상에 대한 글을 써볼까 합니다.

예전에 티스토리에 글을 쓰다가 바빠서 몇달 후에 방문했더니.. 제 블로그가 사라졌더라구요.

백업도 안된다는 말에 당황스러웠던 기억이 있네요.

가급적 1일 글쓰기를 실천할려고 합니다. 그럼

Facebook Comments