Tối ưu BloomFilterService giảm tải với pipeline

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ặc mightContain(), 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.
  • 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);
    }
}