রেডিস কিউ

রেডিস বেসে মেসেজ কিউ এর ব্যাপারে, মেসেজ ডিলে প্রসেসিং সাপোট।

ইন্স্টলেশন

composer require webman/redis-queue

কনফিগিউরেশন ফাইল

রেডিস কনফিগারেশন ফাইলটি স্বয়ংক্রিয়ভাবে জেনারেট হয় config/plugin/webman/redis-queue/redis.php স্থানে, যার কন্টেন্ট নিম্নলিখিত মতোঃ

<?php
return [
    'default' => [
        'host' => 'redis://127.0.0.1:6379',
        'options' => [
            'auth' => '',         // পাসওয়ার্ড, ঐচ্ছিক
            'db' => 0,            // ডাটাবেস
            'max_attempts'  => 5, // সন্দেহজনক তেমন ঘটনা হলে, পুনরায় চেষ্টা করা হবে কতবার
            'retry_seconds' => 5, // পুনরায় চেষ্টা করার মধ্যে বিরামক, সেকেন্ড একক
        ]
    ],
];

চেষ্টা ব্যর্থ হলে পুনরায় চেষ্টা করার ব্যবস্থা

যদি চেষ্টা ব্যর্থ হয়(অজ্ঞাত) হলে, তবে মেসেজটি ডিলে এর জন্য অপেক্ষা করতে হবে। পুনরায় চেষ্টা যাচাইযোগ্যতা এবং প্রদানের জন্য max_attempts প্যারামিটার দ্বারা নিয়ন্ত্রিত হবে, retry_seconds এবং max_attempts এর মাঝে অন্ততঃ retry_seconds বা max_attempts ভাগ। উদাহরণস্বরূপ, যদি max_attempts হয় 5,retry_seconds হয় 10, তাহলে প্রথম পুনরায় চেষ্টার ঘর্ষণ হবে 1*10 সেকেন্ড, দ্বিতীয় হবে 2*10 সেকেন্ড, তৃতীয় হবে 3*10 সেকেন্ড, এইভাবে চলে প্রতি বারই এর পরিবর্তি চেষ্টা 5 বার পর্যন্ত। যদি ক্রমশ পুনরায় চেষ্টা কতবার করা মেয়াদ উত্তীর্ণ হয়, তাহলে মেসেজটি দ্বারা ব্যর্থ দিয়ে দেওয়া হবে {রেডিস-কিউ}─ব্যর্থ নামের অজ্ঞাত্বন্ধীত কিউতে।

মেসেজ পাঠানো (সিংক্রোনাইজড)

দয়া করে দেখান
এটি পরিষ্কার করতে webman/redis >= 1.2.0, দরকার redis এক্সটেনশন

<?php
namespace app\controller;

use support\Request;
use Webman\RedisQueue\Redis;

class Index
{
    public function queue(Request $request)
    {
        // কিউ নাম
        $queue = 'send-mail';
        // ডেটা, সরাসরি অ্যারে পাঠাতে পারেন, সিরিয়ালাইজ করা প্রয়োজন নেই
        $data = ['to' => 'tom@gmail.com', 'content' => 'hello'];
        // মেসেজ পাঠান
        Redis::send($queue, $data);
        // মেসেজ পাঠান মেসেজটি 60 সেকেন্ড পর প্রসেস করা হবে
        Redis::send($queue, $data, 60);

        return response('রেডিস কিউ পরীক্ষা');
    }

}

পাঠানো সফল Redis::send() মেথড ট্রু রিটার্ন করে, পার থাকলে ফলস রিটার্ন করে এবং অথবা ব্যর্থ হলে এক্সেপশন থ্রো করে।

পরামর্শ
দিল কিউ কনসুমপশন সময় কিছু অনিশ্চিত ত্রুটি যেমন কিউ জম যোগ হতে অবহিত হতে পারে, যাতে কিউ বিলম্বিত বসে যায়, যাতে দিল কমানো যায়, এর সাহায্যে এই টাইপ এর সমস্যা আপসন করা যায় এর চিকিৎসার দাবি করা যায়।

মেসেজ পাঠানো (অ্যাসিংক্রোনাস)

<?php
namespace app\controller;

use support\Request;
use Webman\RedisQueue\Client;

class Index
{
    public function queue(Request $request)
    {
        // কিউ নাম
        $queue = 'send-mail';
        // ডেটা, সরাসরি অ্যারে পাঠাতে পারেন, সিরিয়ালাইজ করা প্রয়োজন নেই
        $data = ['to' => 'tom@gmail.com', 'content' => 'hello'];
        // মেসেজ পাঠান
        Client::send($queue, $data);
        // মেসেজ পাঠান মেসেজটি 60 সেকেন্ড পর প্রসেস করা হবে
        Client::send($queue, $data, 60);

        return response('রেডিস কিউ পরীক্ষা');
    }

}

Client::send() এই কোন রিটার্ন ভ্যালু থাকে না, এটি অ্যাসিংক্রোনাস মার্চান্টি, এটি রেডিস এ নিশ্চিত মেসেজ%100 পৌঁছে যাবে না।

পরামর্শ
Client::send() ইংরাজিতে কাজ করে, এটি কেবলমাত্র ওয়ার্কারস্ম্যান-এর স্থানীয় মেয়াদ বাহিত এনভায়রনমেন্টে ব্যবহার করা যাবে, একটি কমান্ড লাইন স্ক্রিপ্ট ব্যবহার করতে হয় সিঙ্ক্রোনাস ইন্টারফেস Redis::send()

অন্য প্রকল্পে মেসেজ পাঠানো

সময়ের বেলা আপনি অন্য প্রকল্পে মেসেজ পাঠাতে অনুমতি পেতেন এবং' আপনি অযোগ্য অ্যাপলিকেশন webman\redis-queue ব্যবহার করা যাচ্ছে না, তাহলে নিম্নলিখিত ফাংশনের সাহায্যে মেসেজ পাঠাতেন কিউতে।

function redis_queue_send($redis, $queue, $data, $delay = 0) {
    $queue_waiting = '{redis-queue}-waiting';
    $queue_delay = '{redis-queue}-delayed';
    $now = time();
    $package_str = json_encode([
        'id'       => rand(),
        'time'     => $now,
        'delay'    => $delay,
        'attempts' => 0,
        'queue'    => $queue,
        'data'     => $data
    ]);
    if ($delay) {
        return $redis->zAdd($queue_delay, $now + $delay, $package_str);
    }
    return $redis->lPush($queue_waiting.$queue, $package_str);
}

এখানে, প্যারামিটার $redis হল রেডিস ইনস্ট্যান্স। উদাহরণস্বরূপ রেডিস এক্সটেনশন ব্যবহার করে এর ব্যবহার হয় নিম্নলিখিতরাকামঃ

$redis = new Redis;
$redis->connect('127.0.0.1', 6379);
$queue = 'user-1';
$data= ['some', 'data'];
redis_queue_send($redis, $queue, $data);

খরচ

খরচ প্রসেস কনফিগারেশন ফাইল অবস্থিত config/plugin/webman/redis-queue/process.php এ।
খরচকারীর ডিরেক্টরি অবস্থিত app/queue/redis/ এ।

কমান্ড php webman redis-queue:consumer my-send-mail চালিয়ে দিলে app/queue/redis/MyMailSend.php ফাইল তৈরি হবে।

পরামর্শ
যদি কমান্ড না থাকে তাহলে নিজেই তৈরি করা যায়।

<?php

namespace app\queue\redis;

use Webman\RedisQueue\Consumer;

class MyMailSend implements Consumer
{
    // খাতানোর নাম
    public $queue = 'send-mail';

    // কানেকশন নাম, যা plugin/webman/redis-queue/redis.php ফাইলের কানেকশন এর সাথে সাথে মেলে।
    public $connection = 'default';

    // খরচ
    public function consume($data)
    {
        // ডাটা ডিসেরিয়াইজ করা প্রয়োজন নেই
        var_export($data); // আউটপুট ['to' => 'tom@gmail.com', 'content' => 'hello']
    }
}

লক্ষ্য করুন
খরচ প্রসেসের মধ্যে কোন উত্ক্ষেপ ও এরর ফেলের হিসেবে খরচ সফলভাবে গণ্য হবে, অন্যথায় খরচের ব্যর্থ হিসেবে গণ্য হবে এবং পুনরাবৃত্তি কিউতে যাবে।
রেডিস-কিউতে কোন অ্যাক সিস্টেম নেই, তাহলে এটি স্বয়ংক্রিয়ভাবে অ্যাক করা যেতে পারে (যদি কোন সমস্যা বা এরর না হয় তাহলে)। খরচ প্রক্রিয়ায় যদি বর্তমান বার্তাটি ব্যাপারে তালিকা করা হয়, তাহলে আপনি স্বত: স্নায়ু উঠাতে পারেন এর জন্য কোন উত্ক্ষেপ ফেলে দিতেই পারেন। এটি বাস্তবে অ্যাক সিস্টেমের সাথে পৃথক নয়।

পরামর্শ
খরচোধারক বহু পার্থিব-বর্তমান এবং একই সময়ে পুনরাবৃত্তি হবে না। পুনর যে বার্তা গণ্য হয়ে যাবে তাদের স্বয়ংক্রিয়ভাবে কিউতে থেকে মুছে যাবে, বা মেনুয়ালি মুছে দেয়া প্রয়োজন হবে না।

পরামর্শ
নতুন খাতা যোগ করতে 'process.php' কনফিগারেশনে অভ্যন্তরীণ পরিবর্তন করা দরকার নেই, বর্তমান খাতা চালকের ক্লাস যোগ করতে শুধুমাত্র app/queue/redis এর অধীনে উপস্থিত কর্মী ক্লাস যোগ করতে হবে এবং ক্লাস প্রপার্টি $queue দ্বারা খাতার নাম নির্ধারণ করতে হবে।

পরামর্শ
উইন্ডোস ব্যবহারকারীদের জন্য ওয়েবম্যান চালানোর জন্য 'php windows.php' নিতে হবে, অন্যথায় খরচ প্রসেস কাজ করবে না।

প্রতিটি খাতা পেয়ে নিষ্ক্রিয় একাধিক খরচ প্রসেস সেট করুন

পূর্বনির্ধারিতভাবে, সমস্ত খাতাধারী একই খরচ প্রসেস শেয়ার করে। তবে, কখনই আমরা কিছু খাতার খরচ প্রসেস মোটো করে চালাতে চাই, যেমন একক অত্যন্ত বিরতির খাতার জন্য আরোগ্য একটি পৃথিবী মধ্যে অত্যন্ত বিগতীকর খাতার জন্য আরোগ্য একটি পৃথিবী মধ্যে অত্যন্ত বিগতীকর খাতার জন্য একটি পৃথিবী মধ্যে একটি অস্তিত্ব স্থাপন করার আমরা চাই, আমরা করতে পারি এমন কাছাকাছি প্রসেস সেট করতে পারি। প্রতিটি খাতাধারী একাধনিক খরচ প্রসেসের জন্য আমাদের সেট করার জন্য, পরিবর্তন করা দরকার হবে app_path() . '/queue/redis/fast' এবং app_path() . '/queue/redis/slow' ডাইরেক্টরির বাবস্থাপনা হয়েছে (লক্ষ্য করুন, খরচকারীর নেইমস্পেস পরিবর্তন করা আবশ্যক)। তাহলে কনফিগারেশন নিম্নলিখিত হতে পারে:

return [
    ...অন্যান্য কনফিগারেশন এটির অংশ ছাড়া...

    'redis_consumer_fast'  => [
        'handler'     => Webman\RedisQueue\Process\Consumer::class,
        'count'       => 8,
        'constructor' => [
            // খরচকারীর ক্লাস ডিরেক্টরি
            'consumer_dir' => app_path() . '/queue/redis/fast'
        ]
    ],
    'redis_consumer_slow'  => [
        'handler'     => Webman\RedisQueue\Process\Consumer::class,
        'count'       => 8,
        'constructor' => [
            // খরচকারীর ক্লাস ডিরেক্টরি
            'consumer_dir' => app_path() . '/queue/redis/slow'
        ]
    ]
];

ডিরেক্টরির বিভাজন এবং প্রসেস সেট করার বিবরণ বিবেচনা করে আমরা খুব সহজেই বিভিন্ন খরচকারীদের জন্য বিভিন্ন খরচ প্রসেস সেট করতে পারি।

বহুরুয়া রেডিস সেটআপ

কনফিগারেশন

config/plugin/webman/redis-queue/redis.php

<?php
return [
    'default' => [
        'host' => 'redis://192.168.0.1:6379',
        'options' => [
            'auth' => null,       // পাসওয়ার্ড, স্ট্রিং টাইপ, ঐচ্ছিক প্যারামিটার
            'db' => 0,            // ডাটাবেস
            'max_attempts'  => 5, // খরচ ব্যতিত হলে, পুনর্চেষ্টা সংখ্যা 
            'retry_seconds' => 5, // পুনর্চেষ্টা অন্তর, ইউনিট: সেকেন্ড
        ]
    ],
    'other' => [
        'host' => 'redis://192.168.0.2:6379',
        'options' => [
            'auth' => null,       // পাসওয়ার্ড, স্ট্রিং টাইপ, ঐচ্ছিক প্যারামিটার
            'db' => 0,             // ডাটাবেস
            'max_attempts'  => 5, // খরচ ব্যতিত হলে, পুনর্চেষ্টা সংখ্যা 
            'retry_seconds' => 5, // পুনর্চেষ্টা অন্তর, ইউনিট: সেকেন্ড
        ]
    ],
];

কনফিগারেশনে আমরা other কে একটি Key হিসাবে অন্তর্ভুক্ত করেছি।

বহুরুয়া রেডিসে মেসেজ প্রেরণ

// `default` কে ম্যাসেজ দিতে
Client::connection('default')->send($queue, $data);
Redis::connection('default')->send($queue, $data);
//  একই অর্থের, 
Client::send($queue, $data);
Redis::send($queue, $data);

// `other` কে ম্যাসেজ দিতে
Client::connection('other')->send($queue, $data);
Redis::connection('other')->send($queue, $data);

বহুরুয়া রেডিস কনসিউমার

খরচ কনফিগারেশনে other কে ম্যাসেজ দিতে

namespace app\queue\redis;

use Webman\RedisQueue\Consumer;

class SendMail implements Consumer
{
    // খাতানোর নাম
    public $queue = 'send-mail';

    // === এই প্যারামিটারটিতে 'other' সেট করা হয়েছে, যেটি খরচ কনফিগারেশনে 'other' কে অন্তর্ভুক্ত করা আছে ===
    public $connection = 'other';

    // খরচ
    public function consume($data)
    {
        // ডাটা ডিসেরিয়াইজ করা প্রয়োজন নেই
        var_export($data);
    }
}

প্রশ্নগুলি

কেন Workerman\Redis\Exception: Workerman Redis Wait Timeout (600 seconds) ত্রুটি দেখা যাচ্ছে?

এই ত্রুটি কেবল অসমঞ্জাস্য ইন্টারফেস Client::send() এ বিদ্যমান। অসমঞ্জাস্য প্রেরণ প্রথমে মেসেজটি লোকাল মেমোরিতে সংরক্ষণ করে রাখে, যখন প্রসেস খালি থাকে তখন মেসেজটির রেডিসে প্রেরণ করা হয়। যদি রেডিস মেসেজ গ্রহণের গতি মেসেজ প্রোডাকশনের গতিতে ধীর হয়, বা প্রসেস সর্বকাল অন্যান্য ব্যবসায়ে ব্যাস্ত থাকে, মেমোরির মেসেজ রেডিসে সমকালে সিঙ্ক না হয়। এটি মেসেজ ভাংচুরের কারণ হতে পারে। যদি মেসেজ ভাংচুর ৬০০ সেকেন্ডের বেশি হয়, তবে এই ত্রুটি সংক্রান্ত হয়।

সমাধান: মেসেজ প্রেরণের জন্য সমকালিন ইন্টারফেস Redis::send() ব্যবহার করুন।