Redis কিউ
Redis-এর উপর ভিত্তি করে বার্তা কিউ, বার্তার বিলম্বিত প্রক্রিয়াকরণের সমর্থন করে।
ইনস্টলেশন
composer require webman/redis-queue
কনফিগারেশন ফাইল
Redis কনফিগারেশন ফাইল স্বয়ংক্রিয়ভাবে তৈরি হয় {প্রধান প্রকল্প}/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
এর সমন্বয়ে নিয়ন্ত্রণ করা হয়। উদাহরণস্বরূপ max_attempts
৫ এবং retry_seconds
১০ হলে, প্রথম পুনরায় চেষ্টা সময়কাল হবে 1*10
সেকেন্ড, দ্বিতীয় পুনরায় চেষ্টা সময়কাল হবে 2*10
সেকেন্ড, তৃতীয় পুনরায় চেষ্টা সময়কাল হবে 3*10
সেকেন্ড, এবং এইভাবে চলতে থাকবে যতক্ষণ না ৫বার পুনরায় চেষ্টা করা হয়। যদি max_attempts
সেট করা সংখ্যাটি অতিক্রম করে, তাহলে বার্তাটি key
হিসেবে {redis-queue}-failed
ব্যবহৃত ব্যর্থ কিউতে রাখা হয়।
বার্তা প্রেরণ (সমলীত)
<?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 queue test');
}
}
সফলভাবে প্রেরণের জন্য Redis::send()
ফেরত দেবে true, নাহলে false অথবা একটি ব্যতিক্রম ছুঁড়ে দিবে।
সূচনা
বিলম্বিত কিউয়ের গ্রহণ সময় অদ্ভুত হতে পারে, যেমন গ্রহণের গতি উৎপাদন গতি থেকে কম হলে কিউ জমা হতে পারে, ফলে গ্রহণ বিলম্ব হতে পারে, সমস্যার সমাধান হিসেবে বেশি সংখ্যক গ্রহণ প্রক্রিয়া খুলুন।
বার্তা প্রেরণ (অসহযোগিত)
<?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('redis queue test');
}
}
Client::send()
কোন ফেরত value নেই, এটি অসংলগ্ন পুশিংয়ের অন্তর্ভুক্ত, এটি বার্তা 100% Redis-এ পৌঁছানোর গ্যারান্টি দেয় না।
সূচনা
Client::send()
এর নীতি হল স্থানীয় মেমোরিতে একটি মেমরি কিউ তৈরি করা, বার্তাগুলোকে অসংলগ্নভাবে Redis-এ সিঙ্করোনাইজ করা (সিঙ্করোনাইজেশন গতি খুব দ্রুত, প্রতি সেকেন্ডে প্রায় 10000 বার্তা)। যদি প্রক্রিয়াটি পুনরায় চালু হয় এবং স্থানীয় মেমরি কিউয়ের ডেটা পুরোপুরি সিঙ্ক্রোনাইজ করা না হয়, তাহলে বার্তা হারিয়ে যেতে পারে।Client::send()
অসংলগ্নভাবে প্রেরণ এমন বার্তাগুলির জন্য উপযুক্ত যা গুরুত্বপূর্ণ নয়।সূচনা
Client::send()
অসংলগ্ন, এটি শুধুমাত্র workerman পরিবেশে ব্যবহার করা যেতে পারে, কমান্ড লাইন স্ক্রিপ্টের জন্য অনুগ্রহ করে সমলীত接口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 উদাহরণ। উদাহরণস্বরূপ 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']
}
// গ্রহণের ব্যর্থতা কলব্যাক
/*
$package = [
'id' => 1357277951, // বার্তা আইডি
'time' => 1709170510, // বার্তা সময়
'delay' => 0, // বিলম্বিত সময়
'attempts' => 2, // গ্রহণের সংখ্যা
'queue' => 'send-mail', // কিউ নাম
'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // বার্তা বিষয়বস্তু
'max_attempts' => 5, // সর্বাধিক পুনরায় চেষ্টা সংখ্যা
'error' => 'ত্রুটির তথ্য' // ত্রুটির তথ্য
]
*/
public function onConsumeFailure(\Throwable $e, $package)
{
echo "consume failure\n";
echo $e->getMessage() . "\n";
// পুনরায় সিরিয়ালাইজ করার প্রয়োজন নেই
var_export($package);
}
}
গুরুত্বপূর্ণ
গ্রহণ প্রক্রিয়ার সময় কোন ব্যতিক্রম এবং ত্রুটি না ঘটলে তা গ্রহণ সফল হিসাবে গণ্য হয়, অন্যথায় গ্রহণ ব্যর্থ হয়, পুনরায় চেষ্টা কিউতে প্রবেশ করে।
redis-queue এর ack মেকানিজম নেই, আপনি এটি স্বয়ংক্রিয় ack (যা ব্যতিক্রম বা ত্রুটি হয়নি) বলার জন্য বিবেচনা করতে পারেন। যদি গ্রহণের প্রক্রিয়ার সময় বর্তমান বার্তাকে গ্রহণ ব্যর্থ হিসাবে চিহ্নিত করতে চান, তাহলে ব্যতিক্রম তুলুন, যাতে বর্তমানে বার্তা পুনরায় চেষ্টা কিউতে প্রবেশ করে। এটি আসলে ack মেকানিজমের সাথে তেমন পার্থক্য নেই।সূচনা
গ্রহণকারীরা বহু সার্ভার এবং বহু প্রক্রিয়া সমর্থন করে, এবং একই বার্তা পুনরায় গ্রহণ হবে না। গ্রহণকৃত বার্তাগুলি স্বয়ংক্রিয়ভাবে কিউ থেকে মুছে ফেলা হয়, ম্যানুয়াল মুছার প্রয়োজন নেই।সূচনা
গ্রহণ প্রক্রিয়া একাধিক বিভিন্ন কিউ গ্রহণ করতে পারে, নতুন কিউ যোগ করার সময়process.php
ফাইলের কনফিগারেশন সংশোধন করতে হবে না, নতুন কিউ গ্রহণকারী কখনওapp/queue/redis
ডিরেক্টরিতে নতুনConsumer
ক্লাস যোগ করে এবং ক্লাসের বৈশিষ্ট্য$queue
দ্বারা গ্রহণের জন্য কিউ নাম নির্ধারণ করতে হবে।সূচনা
উইন্ডোজ ব্যবহারকারীদেরphp windows.php
চালিয়ে webman চালু করতে হবে, অন্যথায় গ্রহণ প্রক্রিয়া চালু হবে না।সূচনা
onConsumeFailure কলব্যাক প্রতিবার গ্রহণ ব্যর্থ হলে সক্রিয় হয়, আপনি এখানে ব্যর্থতা পরবর্তী লজিক পরিচালনা করতে পারেন। (এই বৈশিষ্ট্যটি প্রয়োজনwebman/redis-queue>=1.3.2
workerman/redis-queue>=1.2.1
)
বিভিন্ন কিউয়ের জন্য বিভিন্ন গ্রহণ প্রক্রিয়া সেট করা
ডিফল্টভাবে, সমস্ত গ্রহণকারী একই গ্রহণ প্রক্রিয়া ভাগ করে। কিন্তু কখনও কখনও আমাদের কিছু কিউয়ের গ্রহণকে আলাদা করতে হতে পারে, যেমন ধীর ব্যবসাকৃত কাজকে একটি গোষ্ঠী প্রক্রিয়ায় গ্রহণ করা, এবং দ্রুত গতির কাজকে অন্য একটি গোষ্ঠী প্রক্রিয়ায় গ্রহণ করা। এর জন্য আমরা গ্রহণকারীদের দুইটি ডিরেক্টরিতে ভাগ করতে পারি, যেমন app_path() . '/queue/redis/fast'
এবং app_path() . '/queue/redis/slow'
(গৃহীত ক্লাসের নামকরণশৈলী সঠিকভাবে পরিবর্তন করা প্রয়োজন), কনফিগারেশন হবে নিম্নরূপ:
return [
...এখানে অন্যান্য কনফিগারেশনের অংশ বাদ দেওয়া হলো...
'redis_consumer_fast' => [ // কীটি কাস্টম, ফরম্যাটের কোন সীমাবদ্ধতা নেই, এখানে redis_consumer_fast নামকরণ করা হয়েছে
'handler' => Webman\RedisQueue\Process\Consumer::class,
'count' => 8,
'constructor' => [
// গ্রহণকারীর ক্লাসের ডিরেক্টরি
'consumer_dir' => app_path() . '/queue/redis/fast'
]
],
'redis_consumer_slow' => [ // কীটি কাস্টম, ফরম্যাটের কোন সীমাবদ্ধতা নেই, এখানে redis_consumer_slow নামকরণ করা হয়েছে
'handler' => Webman\RedisQueue\Process\Consumer::class,
'count' => 8,
'constructor' => [
// গ্রহণকারীর ক্লাসের ডিরেক্টরি
'consumer_dir' => app_path() . '/queue/redis/slow'
]
]
];
এভাবে দ্রুত ব্যবসা গ্রহণকারীদের queue/redis/fast
ডিরেক্টরিতে রাখলে, ধীর ব্যবসা গ্রহণকারীদের queue/redis/slow
ডিরেক্টরিতে রাখলে কিউতে নির্দিষ্ট গ্রহণ প্রক্রিয়া দেওয়ার উদ্দেশ্য অর্জিত হবে।
একাধিক redis কনফিগারেশন
কনফিগারেশন
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
কী যুক্ত করুন।
একাধিক redis বার্তা প্রেরণ
// `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);
একাধিক redis গ্রহণ
গৃহীত কনফিগারেশন 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-এ পাঠানো হয়। যদি Redis গ্রহণের গতি বার্তা উৎপাদনের গতি থেকে ধীর হয়, অথবা প্রক্রিয়াটি অন্যান্য ব্যবসায় সময় নিচ্ছে, মেমোরির বার্তাগুলি Redis-এ সিঙ্করোনাইজ করতে পর্যাপ্ত সময় না পায়, তাহলে বার্তাগুলি সঙ্কুচিত হতে পারে। যদি 600 সেকেন্ডের বেশি বার্তা সঙ্কুচিত হয়, তবে এই ত্রুটিটি তৈরি হবে।
সমাধান: বার্তা প্রেরণের জন্য সমলীত পুশিংয়ের ইন্টারফেস Redis::send()
ব্যবহার করুন।