关于队列重复?的一个问题

我也不知道是否应该叫队列重复。先说说我的疑问吧,今天学到这个课程的这个地方突然想到了发红包的问题。
例如条件是每个人只允许发一次红包,用队列来发。
某个用户多次请求这个发红包的操作,会生成多条队列吧?或许可以通过数据库判断这个用户是否发送成功。但是如果是很多并发请求,前面的队列没执行成功,数据库肯定没更新吧,这个怎么判断队列里面有没这个人物呢?
刚才看了下文档,也没说这个问题。或者是我理解的不对,有大佬解惑下吗?

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

我說說我的看法,樓主參考看看
老實說我個人沒有很喜歡在 queue 裡面做資料庫的寫入
一來是除錯變得比較困難
二來資料庫讀寫並沒有慢到需要用 queue 來做
除非有不得已的狀況,例如微服務架構間的通信,或有 10000 筆資料需要批次修改

我會用 queue 通常是兩種狀況:

  1. 使用到第三方服務,沒辦法確保傳輸速度,例如郵件
  2. 對商業模式來說可有可無的任務,例如「有人關注你」的系統通知,收不收到都不影響

上述兩種狀況又對應到一些例外:

  1. 若第三方服務是金流肯定不能用 queue,讓使用者等 30 秒也要確定錢有送出去,以免用 queue 漏掉了
  2. 若同樣以通知來說,「有人購買你的東西」這種通知就對商業模式至關影響了,所以這種狀況也不能用 queue

所以你講的這個情境我會這樣設計

  1. 發紅包請求進來後,先修改資料庫為此人已領過
  2. 將發紅包時間註冊到隊列
  3. 下次重複請求一樣先檢查資料庫,若資料庫顯示已領過則擋掉
  4. 執行隊列後,根據結果判斷是否釋放紅包
6年前 评论
讨论数量: 5

我說說我的看法,樓主參考看看
老實說我個人沒有很喜歡在 queue 裡面做資料庫的寫入
一來是除錯變得比較困難
二來資料庫讀寫並沒有慢到需要用 queue 來做
除非有不得已的狀況,例如微服務架構間的通信,或有 10000 筆資料需要批次修改

我會用 queue 通常是兩種狀況:

  1. 使用到第三方服務,沒辦法確保傳輸速度,例如郵件
  2. 對商業模式來說可有可無的任務,例如「有人關注你」的系統通知,收不收到都不影響

上述兩種狀況又對應到一些例外:

  1. 若第三方服務是金流肯定不能用 queue,讓使用者等 30 秒也要確定錢有送出去,以免用 queue 漏掉了
  2. 若同樣以通知來說,「有人購買你的東西」這種通知就對商業模式至關影響了,所以這種狀況也不能用 queue

所以你講的這個情境我會這樣設計

  1. 發紅包請求進來後,先修改資料庫為此人已領過
  2. 將發紅包時間註冊到隊列
  3. 下次重複請求一樣先檢查資料庫,若資料庫顯示已領過則擋掉
  4. 執行隊列後,根據結果判斷是否釋放紅包
6年前 评论

我說說我的看法,樓主參考看看
老實說我個人沒有很喜歡在 queue 裡面做資料庫的寫入
一來是除錯變得比較困難
二來資料庫讀寫並沒有慢到需要用 queue 來做
除非有不得已的狀況,例如微服務架構間的通信,或有 10000 筆資料需要批次修改

我會用 queue 通常是兩種狀況:

  1. 使用到第三方服務,沒辦法確保傳輸速度,例如郵件
  2. 對商業模式來說可有可無的任務,例如「有人關注你」的系統通知,收不收到都不影響

上述兩種狀況又對應到一些例外:

  1. 若第三方服務是金流肯定不能用 queue,讓使用者等 30 秒也要確定錢有送出去,以免用 queue 漏掉了
  2. 若同樣以通知來說,「有人購買你的東西」這種通知就對商業模式至關影響了,所以這種狀況也不能用 queue

所以你講的這個情境我會這樣設計

  1. 發紅包請求進來後,先修改資料庫為此人已領過
  2. 將發紅包時間註冊到隊列
  3. 下次重複請求一樣先檢查資料庫,若資料庫顯示已領過則擋掉
  4. 執行隊列後,根據結果判斷是否釋放紅包
6年前 评论
TimJuly

你这个问题比较简单,但是可以引申出一个相对复杂的问题。先来说说你提出的问题,同一个用户只能操作一次红包,那么只要保证队列是按顺序执行的即可,简单的来说就是单线程执行或者加锁(分布式系统里如何保证单线程以及如何正确的加锁也是一个复杂的问题,这里不再讨论),同一类型(为什么?请自己思考。)的消息第一个没有处理完毕的时候第二个一定不会被处理,那么等第二个请求进来的时候,去数据库里查一下之前是否有执行过就可以了。

再来说说
@leochien 提到的问题,什么情况下会使用队列,我的理解是只要是时间过长的任务都要放到队列里执行。如果不放到队列里执行会出现什么问题呢,我们来考虑以下情况:

用户发起请求->微服务A->微服务B->微服务C->外部支付系统(时间较长)

那么如果使用同步调用。首先用户体验极差,点了按钮 1 秒钟没反应,我就有关掉的想法了。其次在系统中会维持着大量的网络连接,增加了系统的开销,其中任何一个连接的断开都会使得当前服务调用出现问题,依然会出现账目问题,处理的时间越长,越会增加这种错误的出现。例如:微服务C已经处理完毕,并且成功提交了事物,此时微服务A判断微服务B处理时间过长,自动断掉了连接,然后回滚了自己得事物,那么后面你需要处理的事情复杂度可想而知。

对于有关钱的操作,无论是什么系统,都要进行定期的主动对账,这样就解决了用户付款了没有收到或者重复付款等问题。

6年前 评论
lmaster

@TimJuly 定期的主动对账,很专业,学到了 @leochien 说的茅塞顿开,棒棒的 ~_~ .

6年前 评论
月光

@leochien 从这位老哥这里又学到了一点东西,要是字体用简体就更好了。

5年前 评论

是不是只需要找到队列中有没有这个人的id就行了,那就自己手动去查啊,反正是个链表结构对吧,查看laravel源码可以知道生成的链表的名字,自己使用predis的函数查询这个链表中有没有用户id就行了

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!