redis原子性测试的疑问

我知道redis的单个操作是原子性的,如果在代码中对redis进行多次操作将无法保证整个操作流程的原子性。

比如下面的这段代码中,假设nums这个key的值是50,使用ab.exe工具对其1000次访问,并发数是100,理论上结果应该会出现负数的.

可是我多次测试下nums的值都是1,请问是我测试的方式不对还是其他哪里有问题呢?

$nums = $redis->get('nums');
if($nums > 1)
    $redis->decr('nums');
阅读 3.3k
3 个回答

不知道ab.exe测试时什么原理,你自己写一个多线程调用下就知道了会产生负数值的。

//php不会,用java写了个test。
import redis.clients.jedis.Jedis;


public class Test {
    
    public static void main(String[] args) throws Exception {
        
        Jedis jedis = getJedis();
        jedis.set("nums", 50+"");
        close(jedis);
        
        for(int i = 0;i < 1000;i++){ //启动1000个线程
            new Thread(new MyTask()).start();
        }
        
    }
    
    public static  Jedis getJedis(){
        Jedis j = new Jedis("xxxxx", 6379);
        j.auth("xxxx");
        return j;
    }
    
    public static void close(Jedis jedis){
        if(null == jedis){
            return;
        }
        jedis.close();
    }
}

class MyTask implements Runnable{
    @Override
    public void run() {
        Jedis j = Test.getJedis();
         String numStr = j.get("nums");
         Integer nums = Integer.valueOf(numStr);
        
        if(nums > 1){
             j.decr("nums");
        }else{
             System.out.println(nums);
        }
        Test.close(j);
    }
}

输出结果出现负值。

你写了判断呀,大于1的时候才递减1
你减到1的时候都不执行了,他怎么能作为测试原子性的依据呢?

你这样的并发很难测试出来的,的确这样操作存在负数的可能。但是想想你的电脑是 4核8线程,最多同时执行8个请求而已,这对redis来说是非常小的并发量了。所以我认为不出现问题是因为并发量小了,实际上是会存在问题的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题