报错场景:

 我的代码中用到了redis的布隆过滤器来做瀑布流的推荐与过滤,在压测的时候,因为是多个进程并发访问,这样就导致了以下错误:

org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR Error running script (call to f_7eccf151e55936985c918ea89cf06b0b5205f711): @user_script:1: ERR exbloom is already exists

解决方法:

 很明显是由于并发多个线程同时操作同一个redis布隆过滤器,发生了删除与建立不一致的问题。若加锁可以解决redis报错问题,但是每次都要进行加锁,反而降低了访问效率。

  压测的请求量是50000次,出现的报错小于50次,综合考虑后,这个错误不进行修改了。若报错,直接获取保底数据进行填充瀑布流推荐。

2022年10月24日补充:

上次说到这个错误不进行处理通过保底数据来处理这个问题;

今天又看代码,如下:

// 若已推荐个数为0,说明是第一次推荐,则进行初始化布隆过滤器
if(currentConsumedFeedCnt == 0){
  // 删除该布隆过滤器
  redisUtil.del(RedisConstant.REC_FEEDS_4_BLOOM_UUID_4_CONTENT_IDS+uuid);
  // 新建布隆过滤器
  redisUtil.bfreserve(RedisConstant.REC_FEEDS_4_BLOOM_UUID_4_CONTENT_IDS+uuid, 
   BloomConstant.EXPECT_ERROR_RATE, BloomConstant.EXPECT_STORED_NUM);
}

发现,只有符合推荐数为0的时候才进行删除并重新创建;

若是这样,感觉可以通过加轻量级的锁进行解决,所以优化后代码如下:

// 若已推荐个数为0,说明是第一次推荐,则进行初始化布隆过滤器
if(currentConsumedFeedCnt == 0){
	Lock l = new ReentrantLock();
	l.lock();
	try{
		// 删除该布隆过滤器
		redisUtil.del(RedisConstant.REC_FEEDS_4_BLOOM_UUID_4_CONTENT_IDS+uuid);
		// 新建布隆过滤器
		redisUtil.bfreserve(RedisConstant.REC_FEEDS_4_BLOOM_UUID_4_CONTENT_IDS+uuid, BloomConstant.EXPECT_ERROR_RATE, BloomConstant.EXPECT_STORED_NUM);
	}catch(Exception e){
		log.error("删除或创建布隆过滤器报错:",e.getMessage());
	}finally {
		l.unlock();
	}
}

果然,再给到我们测试的哥哥,进行压测,速度并没有影响多少,反而不进行报错了,perfect!!

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐