برنامه نویسی

فیلترهای شکوفه که در برنامه زندگی واقعی اعمال می شود – نمونه اولیه لاراول

مشکل

وقتی چیزی داریم مکرر و در همان زمان فشرده این فقط یکی از بزرگترین چالش هایی است که ممکن است با آن روبرو شویم.

یک مثال خوب از آن چیزی شبیه است اعتبار سنجی منحصر به فرد؛ ما باید یک ایمیل جدید به پایگاه داده اضافه کنیم ، اما برای انجام این کار باید برای هر ایمیل که در حال حاضر در پایگاه داده است ، بررسی کنیم.
و این شدت آن است. ما یک جدول کامل را انجام می دهیم -در بهترین حالت index– بنابراین ما اطمینان حاصل می کنیم که این جدول نمونه ای از آن ایمیل ندارد.

موردی را در نظر بگیرید که میلیون ها کاربر در جدول کاربران خود داشته باشید و باید مطمئن شوید که ایمیل برای هر کاربر که وارد سیستم می شود بی نظیر است. اعتبارسنجی در واقع خیلی طولانی خواهد شد و کاربر زحمت می کشد.
ناگفته نماند که میزان ریسکی که در پایگاه داده قرار داده اید ، انجام آن اسکن عظیم بر روی مقدار زیادی از داده ها در مورد یک کار ساده به عنوان اعتبار سنجی است.

با توجه به نمونه ما از حدود 10 میلیون کاربر ، ما به آن نیاز داریم ~10-60 seconds بدون نمایه سازی
در حالی که شاید با نمایه سازی ممکن است چند ثانیه طول بکشد.

این اعداد جامد نیستند ، فقط برای مراجعه به میزان آن قدرت گرفتن

مدتی بودن در صنعت می دانید-از این که دریافت کنید ، که داشتن پرس و جو کمتری در پایگاه داده همیشه بهتر است.
به همین دلیل ما شروع کردیم لایه ذخیره مانند مجدداً (که در این وبلاگ نیز استفاده خواهد شد). وت ابزارهای موتور جستجو مانند جستجوی الاستیکبشر و تکیه بر کارگزاران پیام مانند خرگوش برای نگه داشتن صف

استفاده از ابزارهای دیگر برای به حداقل رساندن نیاز به انجام پرس و جو کاری است که ما اغلب در مهندسی نرم افزار انجام می دهیم و این مورد فرقی نمی کند.
بهترین راه حل برای چنین موردی است فیلترهای شکوفه، که در بخش بعدی به تفصیل توضیح خواهم داد.


راه حل: فیلترهای شکوفه

در مورد فیلترهای شکوفه باید درک کنیم که این فقط یک ابزار نیست. واقعاً یک است ساخت داده ها این برای مواردی مانند مواردی که در اینجا صحبت می کنیم بسیار عالی است.

اصل کلی

فیلتر شکوفه از این دو مؤلفه اصلی تشکیل شده است:

  • آرایه بیتی
  • چندین عملکرد هش

کاری که ما انجام می دهیم این است که وقتی یک مورد جدید درج می شود ، از هر یک از آنها استفاده می کنیم توابع هش در مورد آن ، و آنها باید یک شاخص در مورد آرایه بیتی برای تنظیم 1بشر و هنگامی که ما همه را اعمال می کنیم توابع هش ما پر می کنیم آرایه بیتی در مکان های خاصی که همه خواهند بود 1 اگر با همان بررسی کردیم توابع هشبشر

بنابراین وقتی بعد از آن مقداری درج جدید می گیریم استفاده می کنیم توابع هش دوباره روی آنها و اگر تمام شاخص هایی که توابع هش قبلاً پر شده بودند 1 در آرایه بیتی این بدان معنی است که این مورد جدید “ممکن است قبلاً درج شود” (بعداً این را توضیح می دهد).

نمونه

بیایید پرونده ایمیل خود را به عنوان نمونه ای از آن در نظر بگیریم.

وقتی یک ایمیل جدید وارد می کنیم (به عنوان مثال "abdelrahman.dwedar.7350@gmail.com") ما با اجرای توابع هش روی آن و بیایید فقط برای سادگی تصور کنیم که نتایج این بوده است: 7با 1با 5بشر

بنابراین ما آرایه بیتی اکنون به این شکل به نظر می رسد:

[0, 1, 0, 0, 0, 1, 0, 1, 0, 0]
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

توجه داشته باشید که ما داریم 1 در فهرست های حاصل از توابع هشبشر

اگر اکنون سعی می کنیم دوباره به آن بپردازیم "abdelrahman.dwedar.7350@gmail.com" دوباره ما همه آنها را به عنوان خواهیم داشت 1 در حال حاضر ما گمان می کنیم که ممکن است قبلاً درج شده باشد.

ماهیت کاذب مثبت فیلترهای شکوفه

فیلترهای شکوفه یک ساختار داده کاذب مثبت است ، در مورد پرونده false در واقع یک جامد است falseبشر با این حال اگر باشد true من قدرت عمل کردن falseبشر

چگونه این اتفاق دقیقاً رخ می دهد؟

بیایید یک مثال در همین مورد داشته باشیم آرایه بیتی با شاخص ها 7با 1وت 5 پر شدن ممکن است درج شوید "new_email@gmail.com" هنوز شما توابع هش نتیجه نیز 7با 1با 5 این بدان معنی است که در آرایه بیتی، این بدان معنی است که ممکن است درج شود ، بنابراین اکنون باید یک اسکن کامل انجام دهید.

با این حال ، بخش خوب این است که ما مطمئن هستیم که در صورتی که همه آنها پر نشده اند که مورد جدید قبلاً هرگز درج نشده است.

چرا از آن استفاده می کنیم؟

به عنوان فیلترهای شکوفه استفاده از a آرایه بیتی و خیلی سریع توابع هشویی مانند FNV یا صدای زوزه، این یک بررسی بسیار سریع ما را در مورد درج شده با a نتیجه می دهد کاذب مثبت نتیجه

با استفاده از فیلترهای شکوفه باعث می شود که اسکن کامل را بسیار کمتر کنید ، مانند هر زمان که به شما می دهد false شما 100 ٪ اطمینان دارید که قبلاً به پایگاه داده اضافه نشده است.

من توصیه می کنم درباره اطلاعات بیشتر در مورد فیلترهای شکوفه برای به دست آوردن درک بهتر از آن ، بنابراین من چند منبع ارزشمند را که در منابع استفاده کردم اضافه کردم.


فیلترهای شکوفه: اجرای Redis

اجرای مجدد

مجدداً است ، ارزش فروشگاه داده بیشترین استفاده به عنوان لایه حافظه، داده ها را ذخیره می کند در حافظه که رسیدن به هر زمان سریعتر می شود. و ماهیت آن به عنوان یک ارزش فروشگاه داده که شبیه به نقشه های هش این هر دو سرعت خواندن و نوشتن عالی است.

من استفاده خواهم کرد مجدداً برای آن مجدداً به طور پیش فرض اجرای آن را ندارد فیلترهای شکوفه، با این حال می توانید با افزودن ماژول ساختار داده های احتمالی Redis به آن ، آن را داشته باشید مجدداًیا با استفاده از تصویر Docker Redis-Stack. (در نمونه اولیه من از تصویر Docker استفاده کردم).

با استفاده از مجدداً سربار ساخت فیلتر شکوفه از ابتدا در برنامه ما ، و همچنین به شما کمک می کند مقیاس پذیر (که خارج از محدوده این مقاله است) برای بعداً.

دستورات redis

اگر تا به حال استفاده کرده اید مجدداً قبل از اینکه بدانید ما از دستوراتی مانند استفاده می کنیم APPEND {key} {value}بشر

ما دستوراتی برای فیلترهای شکوفه در مجدداً همچنین ، همه آنها با شروع می شوند BFبشر
من به تک تک آنها اشاره نخواهم کرد ، اما مهمترین آنها را به شما می گویم.

  • BF.RESERVE {key} {error_rate} {capacity} [EXPANSION expansion]: برای ظرفیت مشخص شده اولیه و با یک محدوده فوقانی یک فیلتر شکوفه خالی با یک زیر فیلتر واحد ایجاد می کند error_rateبشر
  • BF.ADD {key} {item}: یک مورد را به فیلتر شکوفه اضافه می کند.
  • BF.INSERT {key} ITEMS {item} [item...]: اگر کلید با استفاده از نرخ خطای مشخص شده ، ظرفیت و گسترش وجود ندارد ، یک فیلتر شکوفه جدید ایجاد می کند ، سپس تمام موارد مشخص شده را به فیلتر Bloom اضافه می کند. (حداقل یک مورد را می پذیرد)
  • BF.EXISTS {key} {item}: تعیین می کند که آیا یک مورد خاص به فیلتر شکوفه اضافه شده است یا خیر.

من فکر می کنم فقط با نامگذاری می توانید درک کنید که چگونه کار می کند. ما استفاده خواهیم کرد BF.RESERVE برای ایجاد یک جدید فیلتر شکوفه، و سپس ما استفاده می کنیم BF.ADD یا BF.INSERT برای افزودن موارد جدید به آن (و تابع هش در داخل اجرا خواهد شد) هر زمان که بخواهیم بررسی کنیم که آیا یک مورد در آن وجود دارد فیلتر شکوفه ما استفاده می کنیم BF.EXISTS (که همچنین اجرا می کند توابع هش داخلی)

به سادگی مانند این که اکنون ما یک آماده آماده داریم فیلتر شکوفه برای یک برنامه در مقیاس بالا نیز توسط مقیاس پذیر ویژگی های مجدداًبشر


قوانین اعتبار سنجی سفارشی لاراول

قوانین اعتبار سنجی لاراول چیست؟

برای مثال واقعی زندگی ما به یک برنامه نیاز داریم و در لایه برنامه استفاده می کنم لاراولدر لاراول ما می توانیم قوانین اعتبار سنجی داشته باشیم ، مانند موارد زیر:



$validated = $request->validate([
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
]);
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

در این مثال ، ما داریم title وت body به عنوان زمینه های درخواست ، و قوانین اعتبار سنجی اعمال می شود requiredبا uniqueوت maxبشر

برای ساده کردن آن:

  • required: همانطور که از نام آن نشان می دهد ؛ این یک فیلد مورد نیاز را مورد نیاز قرار می دهد و در صورت عدم اضافه شدن آن خطایی به شما می دهد
  • unique: شما باید یک فیلد منحصر به فرد و نام پس از آن اضافه کنید : نام جدول است که منحصر به فرد بودن آن را بررسی می کند
  • max: حداکثر طول شخصیت را در مورد ما بررسی کنید

قوانین استفاده شده مواردی پیش فرض هستند که از آنجا آمده اند لاراول خود می توانید در اسناد و مدارک اطلاعات بیشتری در مورد آنها کسب کنید.

ایجاد یک قانون اعتبار سنجی سفارشی

لاراول همچنین به شما انعطاف پذیری می دهد تا قوانین سفارشی را همانطور که می خواهید اضافه کنید.

در مورد ما ، unique قانون اعتبار سنجی کافی نیست ، زیرا مستقیماً به پایگاه داده می رود و اسکن کامل جدول را ایجاد می کند.

ما برای آن به چیزی عرف احتیاج داریم.
با پیروی از مستندات برای ایجاد قوانین اعتبار سنجی سفارشی ، می توانیم با اجرای این دستور یک قانون جدید ایجاد کنیم:

php artisan make:rule BloomUnique
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

سپس ما یک الگوی برای قانون جدید داریم.
بعد از اینکه من با استفاده از تغییرات مجدداً با BF.EXISTS این کد نهایی است:



namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Redis;
use App\Models\User;

class BloomUnique implements ValidationRule
{
    protected $filterName;

    public function __construct(string $filterName)
    {
        $this->filterName = $filterName;
    }

    /**
     * Run the validation rule.
     *
     * @param  \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString  $fail
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (Redis::executeRaw(['BF.EXISTS', $this->filterName, $value])) {
            // Check database only if Bloom filter indicates possible existence
            if (User::where($this->filterName, $value)->exists()) {
                $fail('The :attribute has already been taken.');
            }
        }
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

من از Redis کلاس برای اجرای BF.EXISTS فرمان در filterName به درخواست اضافه شده است. با این حال ، ما تمام نشده ایم ، اگر در آن وجود داشته باشد فیلتر شکوفه این بدان معنا نیست که مطمئناً در آنجا وجود دارد ، ما هنوز هم باید یک اسکن جدول درست کنیم تا بررسی کنیم که آیا واقعاً در پایگاه داده است یا خیر.

با این حال در صورتی که ما آن را در فیلتر شکوفه به هیچ وجه ، ما مطمئن هستیم که قبلاً هرگز درج نشده بود.

ما از $fail عملکردی را نشان می دهد که در حال عبور نیست و ما پیام خطا را به عنوان یک پارامتر اضافه می کنیم.


نمونه اولیه

توضیح داده شده

من یک نمونه اولیه برای این کار ساخته ام لاراول وت مجدداًبشر من هم استفاده کردم اسکله برای اجرای آنها

من این مورد را ایجاد کردم که ما فقط از پیش فرض استفاده می کنیم unique قانون اعتبار سنجی.
سپس من این مورد را ایجاد کردم که از قانون سفارشی استفاده کردیم BloomUniqueبشر

هر مورد جداگانه است شاخه گیت، مورد با عادی unique در شاخه ای است without-bloom-filters، و مورد دیگر با قانون سفارشی در شعبه ای نامگذاری شده است with-bloom-filersبشر

من همچنین با استفاده از بذرها اضافه کردم لاراول بذر داخلی برای افزودن داده های آزمایش.

چگونه می توان دوید؟

کلون مخزن

git clone https://github.com/AbdelrahmanDwedar/bloom-filters-validation-laravel-prototype.git
cd laravel-bloom-validation
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

Setup Sail (برای استفاده از Docker)

composer require laravel/sail --dev
php artisan sail:install
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

محیط را تنظیم کنید

cp .env.example .env
./vendor/bin/sail artisan key:generate
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

سپس پیکربندی را برای پایگاه داده اضافه کنید

DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=laravel
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

همچنین ، پیکربندی را برای آن اضافه کنید مجدداً

REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ظروف Docker را شروع کنید و وابستگی ها را نصب کنید

./vendor/bin/sail up -d
./vendor/bin/sail composer install
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

برای تهیه تنظیمات از دستورات سفارشی استفاده کنید

./vendor/bin/sail artisan benchmark:prepare
./vendor/bin/sail artisan benchmark:perform
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این دو دستور سفارشی است که من برای این نمونه اولیه ساخته ام ، اولین مورد benchmark:prepare کار:

  • مهاجرت با یک پایگاه داده تازه
  • بذر را اجرا کنید

و برای benchmark:perform کار این است که

  • معیارها را اجرا کنید
  • آنها را در یک جدول در ترمینال نمایش دهید

پایان

فیلترهای شکوفه ابزاری عالی است که ما ممکن است برای حل مسئله نیاز به ایجاد اسکن کامل با جدول در مواردی که در صورت وجود برخی از زمینه ها در پایگاه داده وجود دارد ، استفاده کنیم.
ما می توانیم با استفاده از آن در سناریوهای زندگی واقعی استفاده کنیم مجدداً اجرای آن ، که من شخصاً آن را تحسین می کنم.

این نمونه اولیه فقط برای نشان دادن چگونگی استفاده از آن در برخی از سناریوهای زندگی واقعی با استفاده از لاراول برنامه ، ما با اضافه کردن قوانین سفارشی در لاراول برای خوانایی بهتر کد و جدایی نگرانی ها.

من در صورت نیاز به اطلاعات بیشتر در مورد آن ، برخی از منابع را که می توانید از آنها در منابع زیر بیشتر یاد بگیرید ، اضافه کرده ام.


منابع

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا