總摘要: spring
2018-01-03
- 摘要: spring注入對象
1. 在springmvc獲取request的方式中,RequestContextListener、.@Autowired,這兩種會不會有并發時的線程安全問題?[河北-波濤]
廣州-小護士<-> 17:27:29
controller注入request對象不會有并發問題
河北-波濤(-) 17:34:27
我也是在網上學習,想到這種問題,這兩種方式的代碼也沒啥特殊的吧,如果我理解無誤應該是:
RequestContextListener:在web.xml配置lisener,在代碼通過全局類獲取(HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
@Autowired:
就是什么request屬性,實現spring自動注入吧
@廣州-小護士 注入式有啥特殊實現嗎?不同方法對應不同request,而注入的是方法公用的類屬性,這樣不會并發時不會有問題,還是我對這兩種方式的理解有誤
成都-梅小西(-) 17:42:17
controller里注入的對象只是線程安全
成都-勇<-> 17:46:12
利用threadlocal 和 ObjectFactory來實現的線程安全,每次在processRequest設置的reqeust對象, 你看FrameworkServlet這個類里面的service()方法嘛
廣州-小護士<-> 17:51:22
先看看 DispatchServlet源碼~
河北-波濤(-) 17:51:58
a請求映射到controller的方法1,b請求映射到方法2,a、b都會對controller的request做注入,如果a、b請求同時發起,方法1和方法2中的去使用這個被注入的request,那這個被注入的request到底是對應哪個請求?這不會用線程安全問題?
成都-勇<-> 17:54:05
你可以簡單的認為每個請求都會啟一個線程來處理,所以threadlocal獲取的對象也不一樣的
廣州-小護士<-> 17:54:45
如果說用到的request不是真實的request,是代理類. 從頭到尾都在代理。注入request對象有兩種方式嘛,一個是方法上傳參,一個是字段注入. 方法傳參很好理解,就是反射調用的時候傳參進去, 字段注入就比較難理解了. 單例模式下也是安全的. Inject HttpServletRequest into Controller
2018-01-08
- 摘要: 線程阻塞
1. 請教大家一個問題,我想限制一個線程池的最大隊列不超過200,如果線程里已經有 core+隊列200 個線程了,就阻塞,直到有線程空出來,才能放入新的線程請求, 有現成的線程池可以實現這樣的功能嗎?[杭州-Freedom]
深圳-rubin(-) 13:59:44
Jdk就可以滿足呀
杭州-Freedom(-) 14:00:30
怎么做?
廣州-揚帆(-) 14:00:44
線程池有四種方式來處理滿了后的線程, 你如果滿了后直接丟棄的話,本身就有的
廣州-小護士<-> 14:00:46
@杭州-Freedom 你到底要隊列還是線程池?
北京-w(-) 14:01:25
newFixedThreadPool
杭州-Freedom(-) 14:02:18
有點像隊列+線程池,因為外部請求會一直不斷的放入,但我想限制線程池最多只能有200個線程
廣州-小護士<-> 14:04:37
我感覺你要的是生產者消費者模式,固定隊列長度
成都-孤狼(-) 14:04:40
線程池不是有一個最大線程數目的參數么
廣州-小護士<-> 14:05:02
PriorityBlockingQueue, DelayQueue, LinkedBlockingQueue, 我推薦的設計是用LinkedBlockingQueue + threadpool
成都-梅小西(-) 14:30:54
直接core=200然后用無限隊列不就行了
杭州-Freedom(-) 18:23:02
最終解決方案: 支持生產阻塞的線程池
2018-01-09
- 摘要: 線程阻塞
1. 下單支付遇到個問題, 下單后事務還沒提交或者提交到數據庫后還沒執行完成,訂單這邊就收到付款成功的MQ 消息,但是此時根據結算號去查找訂單的信息 有幾率出現查詢不到的場景,不知道有啥好辦法規避掉呢? [杭州-水表哥]
北京-喜<-> 17:26:10
這個問題太多了啊. 都不知道該給你出什么方法了
杭州-水表哥(-) 17:26:48
我的問題嗎?
北京-喜<-> 17:27:03
下單后事務還沒提交或者提交到數據庫后還沒執行完成,訂單這邊就收到付款成功的MQ 消息 - 這里有2個問題
北京-Sun(-) 17:27:07
你這個是app端支付完成,但是你訂單都沒生成。
北京-喜<-> 17:27:23
此時根據結算號去查找訂單的信息 有幾率出現查詢不到 - 這里是1個問題, 2, 你訂單沒生成或者沒修改完狀態對面就能付款了?
湖南-stone(-) 17:27:29
應該是先有訂單吧,回調的時候再改狀態啊, 怎么會查不到訂單?這業務不正常吧
杭州-水表哥(-) 17:28:02
下單這邊只是把訂單號和結算信息返回給客戶端,但是這個時候事務是已經提交到數據庫了,但是量大的時候 其實數據庫這個事務都還沒執行完成, 會出現這種場景的 時間 基本精確到10毫秒以內
北京-Sun(-) 17:28:37
那就等事務完成后在返回給客戶端啊。
北京-喜<-> 17:29:10
那就是業務流上 本身是保證不了時序的
杭州-水表哥(-) 17:29:15
這個事務完成后 其實也不可控啊,完全依賴數據庫了
北京-喜<-> 17:29:25
你就需要額外做個 時序派發的處理, 面向狀態機躍遷,自己做個統一的時序控制和排外處理
杭州-水表哥(-) 17:30:12
沒看懂
北京-喜<-> 17:30:15
簡單的說就是,支付回調回來,發現訂單狀態不對。先落地
成都-奮斗(-) 17:30:18
不是應該先把訂單生成成功之后,再提交支付到第三方嗎?
重慶-Rocky(-) 17:30:26
嗯 先存下來, 后期定時跑, 更新
北京-喜<-> 17:30:41
等訂單下單成功之后,反向去解鎖支付回調數據
杭州-水表哥(-) 17:30:43
@ffud 明白你的意思了,也就是所謂的補償
北京-喜<-> 17:30:52
不是補償, 你這個是前半段的技術設計有問題, 在后半段 誰也不知道互相之間的關系, 就得互相檢測, 你完成的時候看看我對不對, 我完成到時候看看你在不在
天津-Michael(-) 17:31:51
下單和支付fork/join
成都-奮斗(-) 17:32:04
喜神,是不是應該先生成了訂單,然后再提交到第三方支付,收到回調消息,更新庫狀態。這是才正常的業務流程吧, 怎么可能你自己的庫的訂單還未生成完成,第三方回調都來了
北京-喜<-> 17:32:37
是的,一般是這樣, 否則有超賣、退款等風險
重慶-Rocky(-) 17:32:55
現在討論的就是這種特殊情況
杭州-水表哥(-) 17:33:21
奮斗,我現在是訂單號和結算號都生成了,事務也提交到數據庫了,只是量大的場景下會出現事務還沒執行完成,客戶端就可以付款,訂單這邊就收到 MQ 消息了
成都-奮斗(-) 17:33:36
恩,明白你的意思, 你們是在訂單事務里面也提交到第三方支付的吧
杭州-水表哥(-) 17:34:13
按照喜神的意思,我可以在收到 支付消息后 如果找不到訂單信息的話 先落地后續再處理這筆單子
北京-喜<-> 17:34:18
就是狀態機 躍遷不是 下單成功-> 支付成功,多了一個 支付成功->下單成功->支付成功, 應該是在事務里RPC了
杭州-水表哥(-) 17:34:55
我沒在訂單事務里面 提交第三方支付的
北京-喜<-> 17:35:14
有異步么
杭州-水表哥(-) 17:35:19
沒異步的, 訂單這邊 只負責生產訂單號和結算號, 客戶端拿到這些數據后去請求支付
北京-喜<-> 17:35:27
沒有的話,就是前面說的第3個問題 主從延遲, 訂單有超時不支付,關閉的動作么?
杭州-水表哥(-) 17:36:16
有的, 我自己判斷應該就是 事務提交到數據庫里面 在排隊等待處理,但是這邊有結算號就可以去支付
北京-喜<-> 17:36:39
有好多方案可以處理,前面提到的可以, 還有一種是解決主從延遲的問題, 加熱點,讀主庫也可以
杭州-水表哥(-) 17:37:23
目前訂單和支付 我這邊都是 讀主庫
北京-Jerry(-) 17:36:38
按照你說的應該會造成長款問題吧
北京-喜<-> 17:37:37
如果一直在讀主庫 出現這個問題
杭州-水表哥(-) 17:37:39
因為之前發生過主從延時 就沒再讀從庫
北京-喜<-> 17:37:42
就是前面的設計的時序不對, 如果不改時序,就用先存儲,后處理的方案
杭州-水表哥(-) 17:38:07
能詳細的說下 哪里的時序不對嗎?
北京-Jerry(-) 17:38:08
你的業務每秒多少筆交易?
杭州-水表哥(-) 17:38:28
每秒有100單的并發量
北京-喜<-> 17:38:25
你提交給三方支付之前, 你對外承諾的業務語義,是你的事情做成功了, 結果支付回調回來之后,發現你沒做成
北京-Jerry(-) 17:38:36
你這個是不是有專門的一個訂單服務的,和交易系統是拆分出來的
杭州-水表哥(-) 17:38:47
這個問題 搞活動的時候會比較明顯
成都-奮斗(-) 17:39:07
強制服主庫
北京-喜<-> 17:39:39
事務沒做完,就把訂單號+訂單狀態返回出去了?
杭州-水表哥(-) 17:39:54
事務只是提交到數據庫, 關鍵我這邊也這邊也不知道數據庫這邊把事務執行完了啊
北京-喜<-> 17:40:40
這個事務不是你們自己的代碼編寫的么?
杭州-水表哥(-) 17:41:00
是的
北京-喜<-> 17:41:06
那怎么會不知道呢, JDBC處理完 你知道的啊
杭州-水表哥(-) 17:42:37
網上我是查了下 有 事務處理成功以后的回調,我今天問下 dba ,他的意思是說 事務只是提交到數據庫了,但是不是提交到數據庫就意味著執行完成了
北京-喜<-> 17:43:17
什么數據庫
杭州-水表哥(-) 17:43:24
mysql
北京-liunx(-) 17:44:07
commit之后成功或者失敗都應該會有一個結果吧?
杭州-東子(-) 17:44:28
@杭州-水表哥 這查錯了吧
杭州-水表哥(-) 17:46:05
怎么說
上海-給你們(-) 17:46:45
從庫策略本來就是做報表之類的查詢用的, 如果實時性要求高就別才用主從這種策略
杭州-水表哥(-) 17:47:03
網上我是看到有 spring 事務提交后的回調處理,也就是說 事務真正提交后再處理后續的。 喜神,求解惑 我也不太想通過 數據線落地再去處理。
北京-喜<-> 17:47:15
不是一件事, 你們DBA說的是 begin 和 commit , begin不等于一定能夠commit, 你的問題是commit后,沒拿到 提交的信息, spring 那個是java的callback,更不是一件事, commit成功或失敗都是可以知道的啊。commit如果返回的是成功,是一定會包成持久化的. 這個是ACID的語義,mysql不能master擴展 也是因為這個原因。本地強一致性,CAP里 不做P。 先落地。后續互相檢查在處理,是可以解決的, 但還是沒找到根本原因。
杭州-水表哥(-) 17:51:05
嗯,這個是第二種方案,還是沒找到根本原因
北京-鵝鵝鵝(-) 17:51:06
mysql就是不做p吧
北京-喜<-> 17:51:15
是啊, 你可以在講講處理流程 , 1 2 3 4這樣列下
上海-給你們(-) 17:52:17
異步支付回調比訂單生成早 在支付回調后沒找到訂單放到隊列里,設置一個重試次數就行了, 從用戶付款到支付回調,我覺得正常情況下不會比生成訂單早,你們訂單生成的真復雜。
北京-alex(-) 17:54:43
一般都是生成訂單在支付的吧
上海-給你們(-) 17:54:52
不一定
北京-alex(-) 17:54:55
也見過不支付不生成訂單的app, 京東淘寶等都是先有訂單在支付的
杭州-水表哥(-) 17:55:39
下單大致流程
1.生成結算號
2.預減庫存
3.執行下單 (生成訂單號,調用支付服務增加結算付款信息)
4.返回客戶端 訂單 結算信息 (后續可以發起支付操作)
北京-喜<-> 17:57:13
全部是同步的?
杭州-水表哥(-) 17:57:52
嗯, 壓根沒異步的場景
北京-喜<-> 17:58:07
那可能是 redo log 到 fsync file system的問題, 你問下DBA, redo log刷盤用的什么策略
杭州-水表哥(-) 17:59:45
mysql 默認的, redo log 刷盤用的是默認的 ,具體是啥我也不懂
北京-喜<-> 18:02:04
就是redo log buffer,會在事務commit的時候,一定持久化到數據文件里
杭州-水表哥(-) 18:03:04
也就是說 只要事務提交了,那就肯定數據都持久化到數據庫了
北京-喜<-> 18:04:02
是的
杭州-水表哥(-) 18:04:27
那我知道啥問題了,目前截圖給群里的代碼是我改造后的,原來的代碼事務是無效的, 原來的事務代碼 只在 executeOrder 這個方法上面加了事務注解,沒生效, 在addOrder 上加了注解就行了.