redis計數器解決用戶同一時間多次提交

思路分析:
    由於用戶網速以及其他原因,前端的js限制沒有起作用,所以要在後端加判斷。由於併發量還算比較大,所以不採用線程鎖。

    思路1:
        在數據庫表格中添加唯一索引
            例如:將userId 和 createTime 綁定成一組唯一索引。如果這兩個值同時相同,不予許插入。
                語句類似於  CONSTRAINT col_2_u UNIQUE (col_1, col_2)
    思路2:
        在數據庫表格中添加一個字段 
            例如:將userId 和 createTime 用,隔開,列爲一個新列,添加時先去查這個列的值是否已經存在。由於消耗資源太多不採用。
    思路3:
        運用緩存機制 redis
            redis 有一個計數器功能, incr 提供保存時間,提供key值就能將key值緩存在redis中並生成一個計數(這個計數起始值是可以指定的,並且在有效時間內每多存一次加一)
    
    最終選用思路3
    使用的incr方法
  /***
     * 
     * @param key 要存的數據
     * @param delta 起始值
     * @param timeout 過期時間
     * @param unit  過期時間單位
     * @return
     */
public Long incr(final String key, final int delta, final long timeout,
			final TimeUnit unit) {

		if (timeout <= 0 || unit == null) {

			return incr(key, delta);
		}
		List<Object> result = redisTemplate
				.executePipelined(new SessionCallback<Object>() {
					@Override
					public <K, V> Object execute(
							RedisOperations<K, V> operations)
							throws DataAccessException {

						ValueOperations<K, V> ops = operations.opsForValue();
						ops.increment((K) key, delta);
						operations.expire((K) key, timeout, unit);

						return null;
					}
				});
		return (Long) result.get(0);
	}
 使用的類
//redisService = SpringHelper.getBean("redisService");
	//話費支付用戶, 使用 redis計數器30秒清空一次 如果30秒內用戶多次點擊購買 incr就不爲1 不做處理即可
	private boolean checkShoppingRepeat(Req10132 req) {
		if(req.getPay_type() == 0){
			Long incr = redisService.incr(req.getUser_id(), 1, 30, TimeUnit.SECONDS);
			
			if(1 != incr){
				return true;
			}
		}
		
		return false;
	}


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