日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

基于TairString實現高效限流器

在限量搶購或者限時秒殺類場景中,除了要有效應對秒殺前后的流量高峰,還需要防止發生接受的下單量超過商品限購數量的問題,Tair(企業版)的TairString數據結構支持簡潔高效的限流器,可以很好地解決訂單超量問題。本文介紹的方案也適用于其它需要限速或者限流的場景。

搶購限流器

exString是Tair新增的數據結構,比原生Redis String功能更加強大,除了比特位(bit)操作外能夠覆蓋原生Redis String的所有功能。

TairString的EXINCRBY/EXINCRBYFLOAT命令與原生Redis String的INCRBY/INCRBYFLOAT命令功能類似,都可對value進行遞增或遞減運算,但EXINCRBY/EXINCRBYFLOAT支持更多選項,例如EXNXVERMINMAX等,詳細說明請參見exString。下文介紹的方案涉及MINMAX兩個選項:

選項

說明

MIN

設置TairString value的最小值。

MAX

設置TairString value的最大值。

使用原生Redis String實現搶購,代碼邏輯復雜,一旦管理不當,容易出現漏網訂單,即明明商品已經搶完,卻還有用戶收到搶購成功的提示,造成不良影響,而使用TairString,只需要非常簡單的代碼即可實現嚴謹的訂單數量限制,偽代碼如下:

if(EXINCRBY(key_iphone, -1, MIN:0) == "would overflow")
    run_out();

限流計數器

搶購限流器類似,使用EXINCRBY命令的MAX選項可以實現限流計數器,偽代碼如下:

if(EXINCRBY(rate_limitor, 1, MAX:1000) == "would overflow")
    traffic_control();

限流計數器的應用場景很多,例如并發限流、訪問頻率限制、密碼修改次數限制等等。以并發限流為例,在請求的并發量突然超過系統的性能限制時,為了防止服務徹底崩潰引發更大的問題,采用限速器限制并發量,保證系統處理能力內的請求得到及時回應,是一種較合理的臨時解決方案。例如配置QPS(Query Per Second)限制,您可以使用TairString的EXINCRBY命令,通過簡單的代碼設置一個并發限流器:

/**
 * tryAcquire is thread-safe and will increment the key from 0 to the upper bound within an interval of time,
 * and return failure once it exceeds
 * @param key the key
 * @param upperBound the max value
 * @param interval the time interval
 * @return acquire success: true; fail: false
 */
public static boolean tryAcquire(String key, int upperBound, int interval) {
    try (Jedis jedis = jedisPool.getResource()) {
        jedis.eval("if redis.call('exists', KEYS[1]) == 1 "
                + "then return redis.call('EXINCRBY', KEYS[1], '1', 'MAX', ARGV[1], 'KEEPTTL') "
                + "else return redis.call('EXSET', KEYS[1], 0, 'EX', ARGV[2]) end",
            Arrays.asList(key), Arrays.asList(String.valueOf(upperBound), String.valueOf(interval)));
        return true;
    } catch (Exception e) {
        if (e.getMessage().contains("increment or decrement would overflow")) {
            return false;
        }
        e.printStackTrace();
    }
    return false;
}