日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

一:需求背景

產品簽到活動需求,對于日活量不高的程序,可以直接使用MySQL去處理,當然數據量不大的話,簽到一次,數據庫簽到表保存一條記錄,也是可以的。但是如果類似京東等商城,那種簽到活動,日活好幾億,并且并發也很高,這樣不斷瘋狂進行數據庫讀寫操作,MySQL壓力是很大的。

 

 

那怎么解決呢?

 

二:解決方案

 

可以利用MySQL,定義一個int類型的字段,4byte=32位,存儲一個月的數據,每次簽到,改變這個字段,程序代碼進行二進制邏輯預算,數據庫該值存儲十進制,優化成一行數據存一個人一個月的簽到記錄。一般商城促銷活動簽到,一個月一個周期已經可以了。

 

三:代碼實現

 

代碼實現前,先來復習一下邏輯運算和簽到邏輯:

 

1.數據庫保存簽到記錄,int類型,4 byte = 32位可以存儲一周或者一個月數據
     周1:0000 0001  == 1
     周2:0000 0010  == 2
     周3:0000 0100  == 4
     周4:0000 1000  == 8
     周5:0001 0000  == 16
     周6:0010 0000  == 32
     周7:0100 0000  == 64
    
2.異或 ^ 、與 & 、或 | 邏輯運算:
     異或 ^:兩者不一樣,eg 1^0,0^1 得出結果就是 1,其他1^1,0^0都是0
     與 &: 只有兩者都是是 1 ,eg 1&1 得出結果就是 1,其他都是0
     或 |: 兩者有一個是 1 ,eg 1^0,0^1,1^1 得出結果就是 1,其他都是0
    
   

 

所以根據上面分析,可以得出以下模擬每天簽到的案例(ps:<< 表示左移):

 

第一天簽到:
1 << 0 == 0000 0001 這時數據庫存的是 1

第二天簽到:
1 << 1 == 0000 0010,此時數據保存前一天簽到 0000 0001,所以需要兩個數據合成一個,可以用 異或 ^  或者 或 |
0000 0010 | 0000 0001 = 0000 0011  或者  0000 0001 ^ 0000 0010 = 0000 0011
這時數據庫存的是 0000 0011 = 3

第三天簽到:
1 << 2 == 0000 0100, 數據庫存的是 0000 0011
0000 0100  | 0000 0011 = 0000 0111  或者  0000 0100 ^ 0000 0011 = 0000 0111
這時數據庫存的是 0000 0111 = 7

第四天沒有簽到


第五天簽到:
1 << 4 == 0001 0000, 數據庫存的是 0000 0111
0001 0000 | 0000 0111 = 0001 0111  或者   0001 0000 ^ 0000 0111 = 0001 0111

........

 

業務層代碼實現,為了方便,代碼模擬一周為一個周期進行簽到:

 

  /**
     * 簽到并領取獎勵
     * @param uid
     * @param day 第幾天
     * @return 簽到成功返回獎勵
     */
public Integer rewardReceiveByDB(String uid, int day) {
        // 查詢當前一周,該用戶是否簽到記錄
        LocalDate now = LocalDate.now();
        LocalDateTime startTime = LocalDateTime.of(now.with(DayOfWeek.MONDAY), LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(now.with(DayOfWeek.SUNDAY), LocalTime.MAX);
        // 查詢是否有本周簽到記錄,一周只有一條記錄
        QueryWrApper<SignLog> wrapper = new QueryWrapper<>();
        wrapper.eq("uid", uid)
                .ge("ctime", startTime)
                .le("ctime", endTime);
        SignLog signLog = signLogService.getOne(wrapper);
        if (signLog == null){
            signLog = new SignLog();
            signLog.setUid(uid);
            signLog.setFlag(0);
        }
        /*
             1 << 2 == 0000 0100, 數據庫存的是 0000 0011
            0000 0100  | 0000 0011 = 0000 0111  或者  0000 0100 ^ 0000 0011 = 0000 0111
       */
        int signFlag = signLog.getFlag();
        // 二進制下標 0開始
        signFlag = signFlag | (1 << (day - 1));
        signLog.setFlag(signFlag);
        signLogService.saveOrUpdate(signLog);

        // Integer.bitCount直接統計,簽到了幾天,發獎勵
        long signInDays = Integer.bitCount(signFlag);
        // todo 根據業務需求,發送獎勵
        return rewardMap.get(signInDays);
    }

   /**
     * 查看用戶在某一天是否簽到了
     * @param uid
     * @param day 第幾天
     * @return
     */
    @Override
    public boolean getSignStatus(String uid, int day) {
        /**
         * 判斷某一天 day 該用戶是否簽到
         * 可用 某一天 day 簽到的 二進制值 跟 當前數據的值 進行 與& 操作,也就是二進制位只有 day 位置是 1,其他都是0,
         *  如果跟它進行 與& 操作 如果數據庫值當天簽到 就會 等于 1
         */
        LocalDate now = LocalDate.now();
        LocalDateTime startTime = LocalDateTime.of(now.with(DayOfWeek.MONDAY), LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(now.with(DayOfWeek.SUNDAY), LocalTime.MAX);
        // 查詢是否有本周簽到記錄,一周只有一條記錄
        QueryWrapper<SignLog> wrapper = new QueryWrapper<>();
        wrapper.eq("uid", uid)
                .ge("ctime", startTime)
                .le("ctime", endTime);
        SignLog signLog = signLogService.getOne(wrapper);
        if (signLog == null){
            return false;
        }
        Integer flag = signLog.getFlag();
        // 當天簽到的二進制值
        int signFlag = 1 << (day - 1);
        return (flag & signFlag) == 1;
    }

 

四:總結

 

個人覺得,具體實現根據公司的業務體量來決定。但是條件允許的話,確實可以用位存儲來實現。其實redis的一個數據類型bitmap也是根據位來實現。方便一點的,可以知己義工redis的bitmap來實現,這樣完全就不用經過數據庫,但是如果需要歸因的話,數據庫保存發送簽到獎勵的記錄即可。

 

本人bitmap實現簽到
:https://blog.csdn.NET/qi_ming88/article/details/102716469

分享到:
標簽:MySQL
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定