php基于redis的lock-free

加速处理队列的方式有很多种,多线程,多进程,多开任务(下文都统称任务)等等,这些方法在并发访问 队列(这里的队列都是指redis的zset) 数据的时候,因为是共享同一个队列,容易产生很多问题。

在众多解决办法中,加锁是最简单粗暴的方法 (目前不考虑同时获取锁的清,php感觉不太好处理,除非c写扩展) 这中锁也叫互斥锁,就是同一时刻只有获得锁的那个任务才有资格去操作共享资源, 别的任务都阻塞住了,被放到了一个叫锁池(Lock pool)的地方,什么事情都干不了,浪费了很多资源。

lock-free无锁队列 一般的是基于CAS(compareAndSet)实现的,但是php操作比较麻烦,得用c写扩展

intcompare_and_swap (int* reg, intoldval, intnewval)  
{  
  intold_reg_val = *reg;  
  if(old_reg_val == oldval)  
     *reg = newval;  
  returnold_reg_val;  
}
复制代码

这里用redis的set实现,原理就是每一个队列访问的时候,它都是只取一个值的,取到值之后,存到set里面,如果有返回0没有则返回1,如果这个时候等于0,那么说明正在有任务处理它,就去取队列的下一个

先生成一些测试数据

    $redis = $this->DomainDrivenDesign('RedisLib');
    $key = "cas:";
    for(;;){
        $value = time()+mt_rand(0,1000000);
        $score = $value+mt_rand(0,1000000);
        $redis->zAdd($key."zset",$value,$score);
    }
复制代码

处理数据代码

        $redis   = $this->DomainDrivenDesign('RedisLib');
        $keyZSet = "cas:zset";
        $keySet  = "cas:zadd";
        for (; ;) {
            ob_flush();
            $start = 0;
            $end   = 0;
            start:
            flush();
            ob_flush();
            $queueVal = $redis->zRevRange($keyZSet, $start, $end)[0];
            $val      = $redis->sAdd($keySet, $queueVal);
            if ($val == 0) {
                $start++;
                $end++;
                goto start;
            }
            for (;;){
                flush();
                ob_flush();
                echo $queueVal . "\r\n";
            }

        }
复制代码

第二个for换成对应处理数据的代码就行了

测试一下,这里同时开了3个

第一个

第二个
第三个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值