01/10/2018, 13:38

Cách tăng tốc độ chạy 1 script PHP + MySQL

em có 1 đoạn code như này

<?php
	include '../connect.php';
	$layvip = mysqli_query($conn, 'SELECT `user_id`, `max_like`, `end`, `likes` FROM vip ORDER BY RAND() LIMIT 10');
	while($vip = mysqli_fetch_assoc($layvip)){
		if($vip['end'] > time()){
			$feed = json_decode(file_get_contents('https://graph.facebook.com/'.$vip['user_id'].'/feed?limit=1&fields=id,likes&method=get&access_token='.$tokenx),true);
			$uid = explode('_', $feed['data'][0]['id'])[0];
        	if(($uid == $vip['user_id']) && ($feed['data'][0]['likes']['count'] < $vip['max_like'])){
				$laytoken = mysqli_query($conn, "SELECT access_token FROM autolike ORDER BY RAND() LIMIT {$vip['likes']}");
				while($token = mysqli_fetch_assoc($laytoken)){
					file_get_contents('https://graph.fb.me/'.$feed['data'][0]['id'].'/likes?access_token='.$token['access_token'].'&method=post');
				}
			}
		}
	}
?>

file này để cron job liên tục chạy like cho các ID Facebook trong cơ sở dữ liệu, nhưng em có 400 recoreds trong bảng vip ( script trên rand id và chọn ra 10 id 1 lần chạy) nhưng khi chạy rất chậm ko lên like nhanh được, e đã Index cho các column cần truy vấn nhiều nhưng vẫn chậm quá, vậy có cách nào tối ưu hơ ko ạ ? $tokenx là 1 mã token trong file connect.php nhé !!!
e cảm ơn!!

Quân viết 15:40 ngày 01/10/2018

Mình không cần biết bạn tối ưu hay tổ chức sql tồi hay tốt đến mức nào nhưng có 1 điểm nghẽn cổ chai chính là phần connect với FB, cứ cho 1 request mất 0.5 s thì với 400 record đã mất 200s rồi, chi mà không chậm

Hoàng Văn Duy viết 15:44 ngày 01/10/2018

có thể dùng nodejs + mysql thay cho php+mysql đc ko nhỉ ?

Quân viết 15:41 ngày 01/10/2018

tùy bạn thôi, nhưng bạn đã thử đo xem nút cổ chai là ở đâu chưa, cứ hùng hục vào tối ưu không phải là cách, vừa mất thời gian mà lại không được gì. Có thể nghĩ sang cách sử dụng đa luồng cũng là 1 cách tăng tốc đối với những job không có liên quan đến nhau

Hoàng Văn Duy viết 15:42 ngày 01/10/2018

php đa luồng ntn bạn ?

Dark.Hades viết 15:46 ngày 01/10/2018

https://secure.php.net/pthreads

Đơn giản là nhét 400 vòng lặp vào 400 hàm/Generator/Anonymous Function, sau đó dùng thread call 400 hàm đó bằng foreach.
Cách dùng luồng này thực sự không ổn vì bạn sẽ gọi khoảng [~400 thread?](tùy vào cấu trúc hệ điều hành/phần cứng).
Nên tìm một thư viện async để chạy. Async nó không hẳn là thread nên có thể thoải mái sử dụng.

Quân viết 15:53 ngày 01/10/2018

hoặc nếu k muốn dùng thư viện ngoài thì chia chunk 400 record ra thành 5-6 phần, cho mỗi phần đó vào 1 thread cũng là 1 cách giảm áp lực cho hệ thống. Còn nếu có kiến thức sâu thì hoàn toàn có thể làm 1 bộ lib async nho nhỏ dựa trên thread

Quang Vu Quang viết 15:50 ngày 01/10/2018

hoặc nếu k muốn dùng thư viện ngoài thì chia chunk 400 record ra thành 5-6 phần, cho mỗi phần đó vào 1 thread cũng là 1 cách giảm áp lực cho hệ thống. Còn nếu có kiến thức sâu thì hoàn toàn có thể làm 1 bộ lib async nho nhỏ dựa trên thread

  1. Về mặt thuật toán: OK
  2. Về mặt tốc độ: bác đang chạy để truy xuất đến API của FB, thông tin đi và về cũng cần thời gian chứ không phải ngay local mà chạy một phát là xong.

Bản chất php là tuần tự, nếu gởi tính hiệu đi nó sẽ đợi tính hiệu về rồi làm tiếp, không khác được. Khí đó bác phải đợi.
Muốn tăng tốc trong trường hợp này bác nên đổi sang Nodejs hoặc chia data trong table [vip] thành nhiều khoản và cho nhiều file/thread chạy song song.

Hoàng Văn Duy viết 15:42 ngày 01/10/2018

chắc em tìm hiểu cài nodejs lên vps em đang dùng là Linux, centos 6 xong là viết file như kia nhưng = nodejs ( .js ) phải không mấy anh ??

Ice Tea viết 15:41 ngày 01/10/2018

Cái này chậm là do gọi nhiều request đến facebook chứ không liên quan MySQL cho lắm.

Có vài cách giải quyết thế này, bạn thử xem sao, mình chưa thử

  • Facebook graph api nó hỗ trợ gọi 1 lúc nhiều id hoặc 1 lúc nhiều requests
    • https://developers.facebook.com/docs/graph-api/using-graph-api#multirequests
    • https://developers.facebook.com/docs/graph-api/making-multiple-requests
  • Sử dụng curl để gọi nhiều request cùng 1 lúc
    • https://www.phpied.com/simultaneuos-http-requests-in-php-with-curl/
    • https://www.onlineaspect.com/2009/01/26/how-to-use-curl_multi-without-blocking/
    • http://rustyrazorblade.com/2008/02/curl_multi_exec/
  • Dùng pthreads như bác Hades nói nhưng cũng chỉ giới hạn 10 id 1 lần chạy cron job nên không lo khoản quá nhiều threads

p/s: NodeJs có tác dụng gì trong trường hợp này nhỉ?

Hung viết 15:41 ngày 01/10/2018

1 đoạn crawling lên GraphQL server đã thấy bất thường rồi.

<?php
file_get_contents('https://graph.fb.me/'.$feed['data'][0]['id'].'/likes?access_token='.$token['access_token'].'&method=post');
Mason Ha viết 15:51 ngày 01/10/2018

Có thể hy sinh bộ nhớ RAM bằng cách Load tất cả dữ liệu của bẳng truy vấn vào 1 biến (cần config php.ini nếu tràn bộ nhớ).

Truy ván SQL không nên dùng RAND() vì CSDL sẽ order rồi shuffle dữ liệu nên hiệu năng giảm. Thay vào đó bạn có thể load vào 1 biến array rồi dùng $arr[rand(min, max)]

Hoàng Văn Duy viết 15:54 ngày 01/10/2018

em đã chuyern sang nodejs và test thành cong trên local, giờ em muốn up len vps và cron chạy tự động thì làm ntn ạ, Cách cron 1 file nodejs trên vps giúp em với ạ!!

Quang Vu Quang viết 15:54 ngày 01/10/2018

Dùng cái này: https://github.com/kelektiv/node-cron

Bài liên quan
0