1
SourceMan 2018-03-02 09:32:28 +08:00 1
|
2
wccc 2018-03-02 09:44:36 +08:00
...有啥难的 简单点 一个线程从 redis 列表取数据 再推送就好了
|
3
liyaojian 2018-03-02 10:01:31 +08:00
送分题,典型的队列应用场景
|
4
chinafeng 2018-03-02 10:45:55 +08:00
为什么会使用 for 循环...
|
5
dangyuluo 2018-03-02 10:46:45 +08:00
beanstalkd,rabbitMQ,太多了
|
6
zonyitoo 2018-03-02 10:47:04 +08:00
居然想到的是用 for 循环…………………………醉
|
7
TANKING OP 谁有一些例子可以看看?
|
8
jswh 2018-03-02 12:10:59 +08:00
这种都用不到那么重的队列,几千个用户......。你的 php 超时是因为在 fpm 里超时吧。你把用户取到之后写到一个文本文件里面,然后在 cli 下跑就好了。如果量不多,手动跑跑也行,或者就写个 cron 定时检查有没有需要跑推送的文件,记得开始推送了对这个文件打个锁标记避免重复推送就好了。
|
9
odirus 2018-03-02 12:34:00 +08:00 1
那啥啥啥,小项目,完全可以就地取材,MySQL 也可以很好地实现消息队列的。。。反正我们小项目都用 MySQL 做消息队列了,多一个组件,多一份危险;大项目再上 MQ,保证 MQ 的高可用性需要花很多精力的。
假设数据表 tab_task 大致这样的: seq_id, is_active, create_time, update_time 其中 is_active = 0 标示待消费的,is_active = 1 表示正在被处理,is_active = 2 标示已经处理好的。 -------------------------------------------------- 正常消费线程,获取一个待处理任务(在一个事务中执行): UPDATE tab_task SET `is_active` = 1 AND `seq_id` = LAST_INSERT_ID(`seq_id`) WHERE AND `is_active` = 0 ORDER BY `seq_id` ASC LIMIT 1; SELECT * FROM tab_task WHERE ROW_COUNT() > 0 AND `seq_id` = LAST_INSERT_ID(); ---------------------------------------------------- 定期检查超时的任务,然后发送报警,获取一个超时的任务(假设超时时间为 5 分钟): SELECT * FROM tab_task WHERE is_active = 1 AND NOW() > DATE_ADD(`update_time`, INTERVAL 5 MINUTE) -------------------------------------------------- |
10
odirus 2018-03-02 12:35:18 +08:00
只要面向接口编程,以后把 MySQL 队列替换成 MQ 队列就很方便
|
11
Enochyun 2018-03-02 12:42:08 +08:00
用 php 脚本跑啊
|
12
opengps 2018-03-02 13:30:26 +08:00
for 循环不是不可以,但是得用独立的线程,控制避免 cpu 连续争用
|
13
shuye00123 2018-03-02 13:42:02 +08:00
为什么要用队列啊,放线程池去运行就好了
|
14
qce7 2018-03-02 13:42:48 +08:00
cli 执行就行了
|
16
zjsxwc 2018-03-02 13:50:14 +08:00
cli 执行怎么会超时
|
17
loveCoding 2018-03-02 13:51:08 +08:00
直接放 redis 吧 ,效率高,不占内存
|
18
alinwu05 2018-03-02 13:51:38 +08:00
这样推送会被微信取消消息模板功能的!!
|
19
jjww 2018-03-02 14:03:27 +08:00
@odirus #9
小项目用 Redis 的 Pub/Sub 或者 List 做消息队列更合适. 对比你的 MySQL 解决方案, 看起来是引入了第三方组件, 其实降低了开发复杂度, 并且稳定性以及效率上提高了不少. 消息的生产者和消费者是不同的进程, 在功能上是解耦的.另外建议对消息用 msgpack 处理一下, 生产者 pack 消费者 unpack. 项目大的话建议用 RabbitMQ 等更成熟的解决方案. |
20
TANKING OP 经测试,用 cli 是可以,不会超时,但是我要做成一个网页版系统,只能用消息队列了。
|
21
TANKING OP @loveCoding 不太会用这个,看了看文档有点麻烦。
|
22
odirus 2018-03-02 14:31:25 +08:00
@jjww
谢谢指教,不过我有不同意见: 经过挖坑、填坑,我其实并不推荐 redis 来实现队列之类的,不确定性太多: 1. 如果我要查询历史消费记录,还是需要存储到其他稳定可靠的介质里面 2. 引入 redis 之后需要考虑维护其稳定性 如果真的是要扩展,我愿意上成熟的方案:例如阿里云的消息队列(当然如果有专门的基础组件研发团队,这又另说) |
23
liuzhedash 2018-03-02 14:52:03 +08:00
|
24
lsvih 2018-03-02 15:23:10 +08:00 via iPhone
滥用模版推送会被封的,亲测
|
25
KgM4gLtF0shViDH3 2018-03-02 15:50:23 +08:00
@TANKING #20 可以用 PHP 调用命令行啊,网页版的也能用的。
|
26
zarte 2018-03-02 16:02:31 +08:00
设置超时时间长点呗
|
27
xsdhy 2018-03-02 17:44:35 +08:00 via Android
如果是有偿技术支持,可以私聊我。
|
28
puritania 2018-03-02 20:18:33 +08:00 via iPhone
最简单的 curl_multi 并发发
|
29
des 2018-03-02 20:29:53 +08:00 via Android
fpm 有办法在超时断开连接继续跑的办法,只不过没法直接返回结果了
或者尝试 workman 及 swoole ? |
30
wangbenjun5 2018-03-02 20:41:59 +08:00
1.数据量不多用 for 循环也没啥大毛病,cli 下面执行脚本就行,用 php 函数 exec 调用脚本就行!
2.使用消息队列,把所有需要发送的消息扔队列里面,然后消费端多开几个进程跑,相等于多线程! |
31
GreatHumorist 2018-03-02 21:02:58 +08:00 1
简答复杂都可以,简单点你可以跑个 cli 死循环,一直读 redis,要在网页操作就往 redis 里抛任务就可以。不用 redis 用 mysql 也行啊,写进 mysql。需要注意的一点是两小时已更新 access_token。
|
32
fcoolish 2018-03-02 21:31:18 +08:00
没人会用 for 循环吧
|
33
TANKING OP @GreatHumorist Access_token 不存进数据库。
|
34
vacker 2018-03-03 01:32:42 +08:00 via Android
说点实际的,我是用的 laravel 队列,运行半年了模板消息没出过问题。
|
35
iyaozhen 2018-03-03 01:34:28 +08:00 via Android
几千用户怕啥。cli 跑几万用户照样 for 循环
|
37
silencefent 2018-03-03 09:17:36 +08:00
redis 存,redis 取,写自动任务,每分钟执行一次 cli 取出列表,foreach 循环拆散了发信,错误了直接关闭
|
39
GreatHumorist 2018-03-03 12:27:47 +08:00
|
40
GreatHumorist 2018-03-03 12:34:01 +08:00
|
41
TANKING OP @GreatHumorist 谢谢
|