- 目录
- 1. 前言
- 2. 消息队列的概念、原理和场景
- 2.1消息队列的概念
- 2.2常见队列及其优缺点
- 2.3消息处理触发机制
- 2.4解耦案例:对垒处理订单系统和配送系统
- 2.4.1架构设计
- 2.4.2程序流程
- 2.4.3创建数据库
- 2.4.4代码实战
- 2.5流量削峰案例:Redis的list类型实现秒杀
- 2.5.1熟悉redis下list类型函数
- 2.5.2创建数据库
- 2.5.3代码实战
- 2.6专业的消息系统RabitMQ实现方案
- 2.6.1 RabitMQ特点
- 2.6.2 RabitMQ安装
- 2.6.3 RabitMQ实战案例
- 3. 总结
1. 前言
很早就了解到消息队列及其架构原理,但很可惜,目前公司暂时用不上这个看似高级的技能点,但为了更好的自我学习,我自己找了些视频学习并做了些demo,希望在未来运用的时候能够快速上手。
代码分享:https://github.com/mtdgclub/messageQueue/tree/dev
2.消息队列的概念、原理和场景
2.1消息队列的概念
消息队列是队列结构的中间件,消息放入后、不需立刻处理,由订阅者/消费者按顺序处理。
2.2常见队列及其优缺点
MySQL:可靠性高、易实现,速度慢
Redis:速度快,单条大消息包时效率低
消息系统:专业性强、可靠,学习成本高
2.3消息处理触发机制
死循环方式读取:易实现,故障时无法及时修复
定时任务:压力均分,有处理量上限
守护进程:类似PHP-FPM和PHP-CG,需要shell基础
2.4解耦案例:对垒处理订单系统和配送系统
2.4.1架构设计
2.4.2程序流程
2.4.3创建数据库
CREATE TABLE `order_queue` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '订单号ID',
`order_id` int(11) NOT NULL,
`mobile` varchar(20) NOT NULL COMMENT '用户的手机号',
`address` varchar(200) NOT NULL COMMENT '用户地址',
`create_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '订单创建时间',
`update_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '订单完成时间',
`status` tinyint(2) NOT NULL COMMENT '当前状态,0 未处理,1 已处理 2 处理中',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.4.4代码实战
待补
2.5流量削峰案例:Redis的list类型实现秒杀
2.5.1熟悉redis下list类型函数
redis的list类型比较核心的几个,通常遵守左进右出原则
LPUSH:将值从列表左侧插入
RPUSH:将值从列表右侧插入
LPOP:移出并获取列表左侧第一个元素
RPOP:移出并获取列表右侧第一个元素
LLEN:获取列表长度
2.5.2创建数据库
CREATE TABLE `m_redis_queue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL DEFAULT '0',
`time_stamp` varchar(24) NOT NULL,
`create_time` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
2.5.3代码实战
2.5.3.1模拟秒杀运行程序
/**
* 秒杀实例
* http://miaosha.com/index.php/index/Miaosha
*/
public function index()
{
$uid = rand(10,100);
//秒杀数量
$num = 10;
if ($this->handle->lLen($this->redis_name) < $num) {
$this->handle->rPush($this->redis_name, $uid . '%' . microtime());
echo '秒杀成功<br/>';
} else {
echo '秒杀结束<br/>';
}
$this->handle->close();
}
秒杀成功:
秒杀结束:
2.5.3.2查看秒杀结果程序
/**
* 存储redis的秒杀数据
* http://miaosha.com/index.php/index/Miaosha/saveQueue
*/
public function saveQueue()
{
while (1) {
$user = $this->handle->lPop(($this->redis_name));
//判断值是否存在
if (!$user || $user == 'nil') {
sleep(1);
continue;
}
//取得时间
$user_arr = explode('%', $user);
$insert_data = array(
'uid' => $user_arr[0],
'time_stamp' => $user_arr[1],
'create_time' =>time()
);
//保存到数据库
$SaveQueueBiz = new SaveQueueBiz();
$res = $SaveQueueBiz->SaveQueueList($insert_data);
//回滚机制
if (!$res) {
$this->handle->lPush($this->redis_name, $user);
}
sleep(1);
}
$this->handle->close();
}
秒杀结果:
2.6专业的消息系统RabitMQ实现方案
2.6.1 RabitMQ特点
完整实现AMQP、集群简化、持久化、跨平台、压力均分、实现类似于负载均衡的效果
2.6.2 RabitMQ安装
1)安装php
sudo apt insatall php
2)查看php版本
php -v
3)安装RabbitMQ
sudo apt install rabbbitmq-server
4)查看RabbitMQ的进程是否正常执行
ps aux|grep rabbitmq
5)安装支持插件
sudo apt install php-bcmatch php-mbstring php-dom php-curl
6)安装composer
apt install composer
7)安装git
sudo apt install git
2.6.3 RabitMQ实战案例
待补
3. 总结
消息队列是流程的中间件,在高并发的秒杀场景或者订单下单场景,能够很好地降低服务器压力,将我们的程序数据维护好。