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 result = redisTemplate
				.executePipelined(new SessionCallback() {
					@Override
					public  Object execute(
							RedisOperations operations)
							throws DataAccessException {

						ValueOperations 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;
	}


你可能感兴趣的:(java)