首页   注册   登录

runnerlee

V2EX 第 162872 号会员,加入于 2016-03-11 12:06:27 +08:00
今日活跃度排名 9657
runnerlee 最近回复了
2 天前
回复了 jy04149886 创建的主题 程序员 mysql gui 客户端推荐一个
TablePlus +1, 前两天刚剁手买了正版, 真香~
3 天前
回复了 shikimoon 创建的主题 程序员 求推荐背包,单肩或者斜跨的
阿迪的双肩包, 哪一款忘了, 挑有独立的笔记本袋那种, 价格两三百.

我那个用了几年了, 好像还有一点防水效果, 一般下雨淋到了外面全湿但内袋还是干的.

有一次跟女朋友搭公交车, 她晕车找不到地方吐就全吐我书包里了, 吐完拉上拉链半个钟后下公交, 一点都没滴出来..
11 天前
回复了 uoddsa 创建的主题 PHP redis 队列推送消息的疑问🤔️
忘了补充一个细节,

在用 lua 调用 lpop 之后, 会将消息 json decode 出来然后自增 attempts 字段, 再放到备份队列.

https://github.com/laravel/framework/blob/5.8/src/Illuminate/Queue/LuaScripts.php#L62

这样是为了实现最大重试次数, 当失败到配置的最大次数之后, 会把消息保存到 mysql 后从 redis 里丢弃掉.
11 天前
回复了 uoddsa 创建的主题 PHP redis 队列推送消息的疑问🤔️
laravel 的做法是同时维护三个队列: 主队列 (list), 备份队列 (reserved, zset) , 延时队列 (delayed, zset).

消息从 list 里 lpop 出来之后会根据超时时间再次存放到备份队列里去, 这个操作用 lua 实现:

https://github.com/laravel/framework/blob/5.8/src/Illuminate/Queue/LuaScripts.php#L54
```
-- Pop the first job off of the queue...
local job = redis.call('lpop', KEYS[1])
local reserved = false
if(job ~= false) then
-- Increment the attempt count and place job on the reserved queue...
reserved = cjson.decode(job)
reserved['attempts'] = reserved['attempts'] + 1
reserved = cjson.encode(reserved)
redis.call('zadd', KEYS[2], ARGV[1], reserved)
redis.call('lpop', KEYS[3])
end
return {job, reserved}
```

而在从主队列 pop 之前, 会根据当前时间从备份队列和延时队列两个 zset 中取出消息 rpush 到主队列中.

https://github.com/laravel/framework/blob/5.8/src/Illuminate/Queue/RedisQueue.php#L167

同样也是使用 lua 进行操作
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Queue/LuaScripts.php#L105
```
-- Get all of the jobs with an expired "score"...
local val = redis.call('zrangebyscore', KEYS[1], '-inf', ARGV[1])

-- If we have values in the array, we will remove them from the first queue
-- and add them onto the destination queue in chunks of 100, which moves
-- all of the appropriate jobs onto the destination queue very safely.
if(next(val) ~= nil) then
redis.call('zremrangebyrank', KEYS[1], 0, #val - 1)

for i = 1, #val, 100 do
redis.call('rpush', KEYS[2], unpack(val, i, math.min(i+99, #val)))
-- Push a notification for every job that was migrated...
for j = i, math.min(i+99, #val) do
redis.call('rpush', KEYS[3], 1)
end
end
end

return val
```

同时为了避免重复消费, 在消息消费成功后, 会手动从备份队列删除备份消息.

https://github.com/laravel/framework/blob/5.8/src/Illuminate/Queue/Jobs/RedisJob.php#L84

在每次 pop 出消息并进行消费之前, 会注册一个 timeoutHandler, 通过计时器来实现中断超时任务

https://github.com/laravel/framework/blob/5.8/src/Illuminate/Queue/Worker.php#L111

所以, 当消费过程中发生异常退出或是超时中断后, 会根据重试时间, 从备份队列里面取出备份消息重新消费.
支持~
用 ubuntu 的时候, 我习惯是 apt 装 php 跟 nginx, 然后用 homestead. 但现在推荐用 docker, 对于开发环境非常便利.

可以看下这个: https://laradock.io/
@SharkIng 哈哈, 我也很不爽, 打了洞治疗完, 说得拍个 X 光, 拍完还说不行得拍个 CT
@caomu 我的看法是, 另外一个医生如果能先让拍片再治疗就不会白白钻个孔. 结合另外一位医生的说法, 他应该虽有副主任医师的 title 但医术相对弱鸡.
关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1159 人在线   最高记录 5043   ·  
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.3 · 8ms · UTC 17:59 · PVG 01:59 · LAX 10:59 · JFK 13:59
♥ Do have faith in what you're doing.
沪ICP备16043287号-1