Redis限制N小時內每用戶Id最多隻能登錄M次解決方案

package com.zxl.redis.rediscode;


import redis.clients.jedis.Jedis;

import java.util.List;

/**
 * @author xiaoliang
 * @date 2020/5/12 21:30
 * @since V1.0
 */
public class LoginValidate {
    //設置成10s是因爲方便測試
    //週期時間爲毫秒
    final static int EXPIRE_TIME_MILLISECOND = 10*1000;
    //一個週期內最多的操作次數
    final static int MOST_TIMES_IN_TIME_LIMIT = 5;

    public static void main(String[] args) {
        //創建Jedis客戶端
        Jedis jedis = new Jedis("192.168.0.3",6379);
        //操作數據
        jedis.select(0);
        //模擬登入用戶
         String userId="zxl";
        loginValidateWithQueue(jedis,userId);
        loginValidateWithQueue(jedis,userId);
        loginValidateWithQueue(jedis,userId);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        loginValidateWithQueue(jedis,userId);
        loginValidateWithQueue(jedis,userId);
        loginValidateWithQueue(jedis,userId);
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        loginValidateWithQueue(jedis,userId);
        loginValidateWithQueue(jedis,userId);
        //取出用戶最後五次的操作時間
        List<String> values=jedis.lrange(userId,0,-1);
        for (int i = 0; i < values.size(); i++) {
            System.out.printf(values.get(i) + "\n");
        }
        //刪除用戶列表
        jedis.del(userId);
        jedis.close();
    }

    /**
     * 用Redis和任意語言實現一段惡意登錄保護的代碼,限制1小時內每用戶Id最多隻能登錄5次
     *
     * @param jedis
     * @param userId
     * @return
     */
    public static boolean loginValidateWithQueue(Jedis jedis, String userId) {
        Long currentTime = System.currentTimeMillis();
        //判斷List列表長度是否超過操作次數
        if (jedis.llen(userId) < MOST_TIMES_IN_TIME_LIMIT) {
            //將當前操作時間放入到用戶list中
            jedis.rpush(userId, currentTime.toString());
            System.out.println(currentTime + " 登入成功!" + jedis.llen(userId));
            return true;
        } else {
            //如果超過操作次數則取出list中最早操作時間,即list下標爲0的
            String earliestTimeStr = jedis.lindex(userId, 0);
            //將字符串轉爲長整形
            Long earliestTime = Long.valueOf(earliestTimeStr);
            //判斷最早操作時間是否在週期內,如果在週期內說明在這個週期內操作數已到閥值不允許再操作。
            if (currentTime - earliestTime <= EXPIRE_TIME_MILLISECOND) {
                System.out.println(EXPIRE_TIME_MILLISECOND/1000 + " 秒內只能操作" + MOST_TIMES_IN_TIME_LIMIT + " 次");
                return false;
            } else {
                //如果最早操作時間不再週期,說明可以繼續操作。
                //爲了使用戶列表長度爲操作次數。需要刪除最早的操作時間,保存本次操作時間。
                //刪除列表尾段數據,即最早操作時間。
                jedis.lpop(userId);
                //插入當前操作時間
                jedis.rpush(userId, currentTime.toString());
                System.out.println(currentTime + " 登入成功!" + jedis.llen(userId));
                return true;
            }
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章