我不太明白这个词怎么表达
是这样的,现在有一台服务器运行数据库(server
),另外一台运行php程序(client
),浏览器(Browser
)访问client
,然后client
逻辑判断后通过http
协议对server
中的数据库进行CURD
操作
有个问题就是,如果Browser
的用户操作过快,而server
和client
之间http请求太慢的话,就会导致client
上获取的数据更新不及时,导致一些错误。。
栗子:一个用户只能买一个商品,用户点击之后,client
先读取server
的数据,判断是否已经购买,没有购买的话进行写入操作,然后购买完成,但是如果用户连着点击两次购买,两次操作一次进入client
,然后由于client
和server
之间网速或者其他一些问题,写入操作没有及时完成,造成两次购买操作的判断为此用户未购买,于是会有两次写入server
数据库的操作,就会造成错误。。
这个问题属于什么?应该怎么解决?
用記憶體資料庫或NOSQL資料庫來跟客戶端交互,然後記憶體資料庫跟MYSQL這類關係型資料庫「同步」。
如果客戶端某些操作需要資料庫查詢來判斷,這個時候如果是高並發的情況很容易就產生錯誤了。以前就經歷過,例如用戶註冊判斷是否有重名的,理論上是先查詢資料庫是否有該用戶名存在然後插入,然而實際運營中這個邏輯竟然被打破了,發現了重名用戶。
所以把核心的資料放到關聯式資料庫,對速度有要求的使用記憶體資料庫。適當的使用快取以減少重複的查詢。
一般的解決方案是伺服器先提供 token,有 token 才能成功操作,用完就會被標記過期。這樣既可以確保不會重複操作,還可以做限流等功能。
而你的問有些不對題。如果是資料庫與業務伺服器之間通訊的安全性,可以使用 SSL 協定。
還有一種做法是採用一致性哈希算出業務 id,不用自增 id。這樣就可以確保很多操作冪等,有興趣可以試試看。
謝邀,你的栗子客戶端做判斷即可
分配token之類的當然是非常好的解決方案。不過在實際應用上我覺得下面這種方案比較簡潔有效率:
前台js裡面處理下,點選【購買】按鈕後彈出全螢幕遮罩,阻止使用者點擊第二次,當後台成功後再把遮罩幹掉。另外也可以使用標誌位的方式,或是使用經典的debounce/throttle演算法。
後台在購買流程中也判斷下,短時間內(例如10秒內)的重複購買的時候直接返回「請不要重複操作」的錯誤。資料庫方面可以考慮使用事務並將事務的隔離等級提高,或使用鎖。
一般前台js裡面處理下後,很多問題都能避免了。除非有惡意使用者。
加上並發鎖,可以使用redis,memcached等,當一條請求完成後再釋放鎖
從上面看你有兩台伺服器,一台運行php的server,另一台db的server。然而你兩台server之間的通訊為什麼要使用http協定呢?而不是走mysql(假設你用的是mysql)預設的連線協定了?也就是說你應該在php中直接連到你server的資料庫,然後操作DB。
對於你例子中提到的連續插入問題,可以透過表格結構設計來完成,可以為欄位新增唯一索引UNIQUE。另外還有一些其它方法,個人比較推薦唯一索引做法