Tối ưu BloomFilterService giảm tải với pipeline
Trong bài viết ta đã dùng bloom filter : https://dev.truyenvideo.com/p/laravel-tao-service-bloomfilterservice-co-chuc-nang-kiem-tra-nhanh-email-co-the-ap-dung-vao-nhieu-viec-khac
Dưới đây ta sẽ tối ưu code với :
-
Giảm số lần kết nối Redis:
- Hiện tại, mỗi lần gọi
add()
hoặcmightContain()
, bạn đang gọi$this->redisconnect
nhiều lần. - Thay vì gọi nhiều lệnh riêng lẻ, ta có thể gom thành pipeline để giảm số lần round-trip đến Redis.
- Hiện tại, mỗi lần gọi
-
Cải thiện
hash()
:crc32()
có thể dẫn đến va chạm hash nhiều hơn so với MurmurHash (hiệu suất tốt hơn cho Bloom Filter).- Nếu có thể, bạn nên dùng
hash('murmur3', $value . $seed)
hoặc một hàm hash mạnh hơn.
-
Tăng hiệu suất với
pipeline()
:- Redis hỗ trợ pipeline giúp thực hiện nhiều lệnh cùng lúc, tăng tốc đáng kể.
- Ta áp dụng
pipeline()
khi set bit để tối ưu tốc độ.
namespace App\Services;
use Illuminate\Support\Facades\Redis;
class BloomFilterService
{
protected int $size;
protected int $hashFunctions;
protected string $redisKey;
protected \Illuminate\Redis\Connections\Connection $redisconnect;
public function __construct(int $size = 10000000, string $connect_key = 'default', $hashFunctions = 10, string $redisKey = 'bloom_filter_emails')
{
$this->size = $size;
$this->redisKey = $redisKey;
$this->redisconnect = Redis::connection($connect_key);
$this->hashFunctions = $hashFunctions;
}
private function hash($value, $seed)
{
return abs(crc32($value . $seed) % $this->size);
}
// ✅ Dùng pipeline để giảm số lệnh gửi đến Redis
public function add($email)
{
$this->redisconnect->pipeline(function ($pipe) use ($email) {
for ($i = 0; $i < $this->hashFunctions; $i++) {
$index = $this->hash($email, $i);
$pipe->setbit($this->redisKey, $index, 1);
}
});
}
// ✅ Tương tự, dùng pipeline cho `mightContain`
public function mightContain($email)
{
$indexes = [];
for ($i = 0; $i < $this->hashFunctions; $i++) {
$indexes[] = $this->hash($email, $i);
}
$results = $this->redisconnect->pipeline(function ($pipe) use ($indexes) {
foreach ($indexes as $index) {
$pipe->getbit($this->redisKey, $index);
}
});
return !in_array(0, $results, true);
}
public function clear()
{
$this->redisconnect->del($this->redisKey);
}
}