發放啟用碼,如何保證一個使用者只能得到一個?

來源:互聯網
上載者:User
我現在事先擁有1萬個啟用碼,要求使用者請求(能拿到使用者id)時,從這1萬個啟用碼抽出一個給使用者,每個使用者最多隻能拿到1個。

我現在的設計是這樣的:
用redis儲存這個1萬個啟用碼的id(主鍵自增,從1到1萬),當使用者請求時,從redis中拿出一個id。利用redis的原子性,可以保每個請求拿到的都是不同的啟用碼。
然後根據id到mysql裡查到這個啟用碼,狀態置為“已發放”,同時在記錄表裡添加“使用者id,啟用碼id”的記錄,再把啟用碼實際內容返回給使用者。這樣使用者每次請求,先查下記錄表有沒有這個使用者記錄,有的話就表示抽過了返回提示資訊,沒有的話就抽取啟用碼返回給使用者。

本來我以為沒問題的,卻發現實際上記錄表出現了1個使用者拿到2個啟用碼的情況,這2條記錄都是同一秒產生的。我猜測可能是這樣的:某個使用者發出了2次請求,這2次請求的時間間隔非常小,所以導致第2次請求檢測記錄表記錄時,第一次請求的“插入記錄表操作”還沒完成,導致2次請求都通過了。

請問是這個原因嗎?要保證一個使用者最多隻能拿到一個該怎麼做呢?

回複內容:

我現在事先擁有1萬個啟用碼,要求使用者請求(能拿到使用者id)時,從這1萬個啟用碼抽出一個給使用者,每個使用者最多隻能拿到1個。

我現在的設計是這樣的:
用redis儲存這個1萬個啟用碼的id(主鍵自增,從1到1萬),當使用者請求時,從redis中拿出一個id。利用redis的原子性,可以保每個請求拿到的都是不同的啟用碼。
然後根據id到mysql裡查到這個啟用碼,狀態置為“已發放”,同時在記錄表裡添加“使用者id,啟用碼id”的記錄,再把啟用碼實際內容返回給使用者。這樣使用者每次請求,先查下記錄表有沒有這個使用者記錄,有的話就表示抽過了返回提示資訊,沒有的話就抽取啟用碼返回給使用者。

本來我以為沒問題的,卻發現實際上記錄表出現了1個使用者拿到2個啟用碼的情況,這2條記錄都是同一秒產生的。我猜測可能是這樣的:某個使用者發出了2次請求,這2次請求的時間間隔非常小,所以導致第2次請求檢測記錄表記錄時,第一次請求的“插入記錄表操作”還沒完成,導致2次請求都通過了。

請問是這個原因嗎?要保證一個使用者最多隻能拿到一個該怎麼做呢?

在插入mysql的時候再做一次驗證

使用一定的演算法,根據使用者ID產生對應的啟用碼,然後入庫。

保證唯一,而且不會重複。

這樣怎麼樣

用戶端提交一次後在收到傳回值之前不可操作。
一定要callback才解鎖

為什麼不先把"使用者id,啟用碼id"的記錄也先存在redis呢?

直接在redis中存邀請碼的消耗情況不行麼?

如果是不小心被點擊了兩次的話,那為什麼不用JS限制只可以點擊一次呢?或者是在提交的時候產生一個唯一的 token 呢?
這不是可以解決了嗎?

使用者操作加鎖就可以:)
在對db等進行操作前. 根據使用者資訊例如 account 產生md5 key 查詢在memcache中是否有值 不存在key 則set 完成db插入等操作 del掉key

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.