Cache query trong ứng dụng thực tế
Ở đây mình có 1 bài toán thực tế đó chính là cache dữ liệu api gọi đến server với thông tin lấy từ trong mysql
Nguồn dữ liệu của mình ổn định và có 1 ít đọc ghi dữ liệu trong quá trình cache :
1 Thực tế website
Thực tế website mình sẽ có lượng truy cập vào trong web cao trong khoảng thời gian từ 9h sáng đến 23h đêm . Việc gọi Api sẽ thường xuyên trong khoảng thời gian này .Việc cập nhật dữ liệu thì sẽ được thực hiện trong khoảng 7,8h sáng
2 : Phương hướng xử lý
Việc đầu tiên thì chắc chắn sẽ phải cache lại thông tin dữ liệu :
Thông thường với dữ liệu nếu thay đổi theo 1 khoản thời gian cụ thể thì mình sẽ dev cache 1 cục sau đó sẽ xử lý với các hàm xử lý array :
$all_data = Cache::remember('all_data', 86400, function () {
return DB::table('excels')->get(['MNT', 'NAME'])->toArray();
});
Như vậy thì nhanh hơn và tiện hơn . Chỉ cần truy vấn sql 1 lần duy nhất
Nhưng vấn đề ở đây là chúng ta lại có dữ liệu người dùng nhập lẻ tẻ không vào 1 thời gian cố định nào và trong thời gian lượng người truy cập cao do đó mình đưa ra phương án 2 đó chính là cache từng phần tử 1 ,Khi nào có phần tử mới thì mình cache luôn phần tử đó .
Bước xử lý như sau :
Bước 1 Cache dữ liệu lúc 2h sáng với schedule :
Mình tạo schedule cache dữ liệu với command sau :
php artisan make:command ExcelDMS
Với nội dung như sau :
<?php
namespace App\Console\Commands;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class CacheDMS extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:cache-d-m-s';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command cache thông tin của khách hàng';
/**
* Execute the console command.
*/
public function handle(): void
{
// $this->info('Bắt đầu chạy ' . Carbon::now());
$status = DB::table('excels')->select(['id', 'MNT', 'NAME'])->chunkById(1000, function ($items) {
foreach ($items as $item) {
Cache::remember($item->MNT, 8600, function () use ($item) {
return $item;
});
}
});
if($status){
$this->info(Carbon::now().'-run');
}else{
$this->error( Carbon::now() .'-error');
}
}
}
Và cấu hình schedule như sau :
$schedule->command('app:cache-d-m-s')->dailyAt('1:50')->appendOutputTo(storage_path('logs\schedule.log'));
Ở trong file api :
$id_search = $request->id;
$data = Cache::remember($id_search, 86300, function () use ($id_search) {
return DB::table('excels')->where('MNT', 'like', $id_search)->get(['MNT', 'NAME']);
});
return \response()->json($data);
Trong file api.php của thư mục routers
Route::get('excel/{id}',[\App\Http\Controllers\Api\ExcelController::class,'index']);
Oke vậy là xong mình đã có 1 api vừa nhanh vừa đỡ truy cập mysql nhiều tránh sập server