复述的最大并发量是多少

  介绍

本篇文章给大家分享的是有关复述的最大并发量是多少,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,<强>复述中的并发问题

使用复述,作为缓存已经很久了,复述是以单进程的形式运行的,命令是一个接着一个执行的,一直以为不会存在并发的问题,直到今天看到相关的资料,才恍然大悟。

<强>具体问题实例

有个键,假设名称为myNum,里面保存的是阿拉伯数字,假设现在值为1,存在多个连接对myNum进行操作的情况,这个时候就会有并发的问题。假设有两个连接linkA和linkB,这两个连接都执行下面的操作,取出myNum的值,+ 1,然后再存回去,看看下面的交互:

linkA得到myNum=比;1 linkb得到myNum=比;1组linka muNum=比;2组linkb myNum=比;2

执行完操作之后,结果可能是2,这和我们预期的3不一致。

再看一个具体的例子:

& lt; ?phprequire“供应商/autoload.php"; $客户=new Predis \客户([   & # 39;计划# 39;=比;& # 39;tcp # 39;   & # 39;主机# 39;=比;& # 39;127.0.0.1 # 39;   & # 39;港口# 39;=比;6379年,]);($ i=0;美元我& lt;1000;我+ +){num美元=intval中(客户→美元(“name"));   num=num + 1美元;   客户→美元setex (“name", num美元,10080);   usleep (10000);}

设置的名字初始值为0,然后同时用两个终端执行上面的程序,最后名称的值可能不是2000年,而是一个& lt; 2000年的值,这也就证明了我们上面的并发问题的存在,这个该怎么解决呢?

<强>复述中的事务

复述中也是有事务的,不过这个事务没有mysql中的完善,只保证了一致性和隔离性,不满足原子性和持久性。

复述,事务使用<强>多,<强>执行强命令

原子性,复述,会将事务中的所有命令执行一遍,哪怕是中间有执行失败也不会回滚.kill信号,宿主机宕机等导致事务执行失败,复述,也不会进行重试或者回滚。

持久性,复述,事务的持久性依赖于复述所使用的持久化模式,遗憾的是各种持久化模式也都不是持久化的。

隔离性,复述是单进程,开启事务之后,会执行完当前连接的所有命令直到遇到exec命令,才处理其他连接的命令。

一致性,看了文档,觉得挺扯的,但是貌似说的没有问题。

复述中的事务不支持原子性,所以解决不了上面的问题。

当然了复述,还有一个<强>看命令强劲,这个命令可以解决这个问题,看下面的例子,对一个键执行手表,然后执行事务,由于手表的存在,他会监测键,当一个被修该之后,后面的事务就会执行失败,这就确保了多个连接同时来了,都监测着,只有一个能执行成功,其他都返回失败。

127.0.0.1:6379>设置一个1 ok127.0.0.1:6379>看aOK127.0.0.1:6379>多OK127.0.0.1:6379>增加aQUEUED127.0.0.1:6379>exec1)(整数)2   127.0.0.1:6379>得到a" 2,

失败时候的例子,从最后可以看的出,测试的值被其他连接修改了:

127.0.0.1:6379>设置测试1 ok127.0.0.1:6379>看testOK127.0.0.1:6379>multiOK127.0.0.1:6379>incrby测试11 queued127.0.0.1:6379>exec(零)   127.0.0.1:6379>test" 100年“

<强>问题如何解决

复述中命令是满足原子性的,因此在值为阿拉伯数字的时候,我可以将获取和设置命令修改为增加或者incrby来解决这个问题,下面的代码开启两个终端同时执行,得到的结果是满足我们预期的2000 .

& lt; ?phprequire“供应商/autoload.php"; $客户=new Predis \客户([   & # 39;计划# 39;=比;& # 39;tcp # 39;   & # 39;主机# 39;=比;& # 39;127.0.0.1 # 39;   & # 39;港口# 39;=比;6379年,]);($ i=0;美元我& lt;1000;我+ +){客户→美元增加(“name");   客户→美元到期(“name", 10800);   usleep (10000);}

确实可行,效果还不错,这里写了个例子

& lt; ?phprequire“供应商/autoload.php"; $客户=new Predis \客户([   & # 39;计划# 39;=比;& # 39;tcp # 39;   & # 39;主机# 39;=比;& # 39;127.0.0.1 # 39;   & # 39;港口# 39;=比;6379年]);类RedisLock{公共美元objRedis=零;   公共超时=3美元;/* * * @desc设置复述,实例* * @param obj对象|复述,实例*/公共函数__construct (obj美元)   {$ this→objRedis=$ obj;   }/* * * @desc获取锁键名*/公共函数getLockCacheKey(键)   {返回“lock_{$关键}“;   }/* * * @desc获取锁* * @param关键字符串|要上锁的键名* @param超时int |上锁时间*/公共函数getLock(键,超时美元=NULL)=${$超时超时?超时:这→美元超时;   lockCacheKey=这→美元getLockCacheKey(关键);   expireAt=时间()+美元超时;   isGet=(bool)这→美元objRedis→setnx (lockCacheKey, expireAt美元);   如果(isGet美元){返回expireAt美元;   },(1){usleep (10);   $=时间();   oldExpire=这→美元objRedis→(lockCacheKey美元);   如果($ oldExpire祝辞=$时间){继续;   }$ newExpire=时间+美元超时;   expireAt=这→美元objRedis→getset (lockCacheKey, newExpire美元);   如果($ oldExpire !=expireAt美元){继续;   }isGet=newExpire美元;   打破;   }返回isGet美元;   }/* * * @desc释放锁* * @param关键字符串|加锁的字段* @param newExpire int |加锁的截止时间* * @return bool |是否释放成功*/公共函数releaseLock(键,newExpire美元)   {$ lockCacheKey=$ this→getLockCacheKey(关键);   如果($ newExpire祝辞=时间()){返回$ this→objRedis→德尔($ lockCacheKey);   }返回true;   }   }$ start_time=microtime(真正);锁定美元=new RedisLock(客户端)美元;$关键=皀ame" ($ i=0;美元我& lt;10000;我+ +){newExpire美元=$锁→getLock(关键);   num=客户→美元(美元键);   美元num + +;   客户→美元(键,num美元);   锁→美元releaseLock(键,newExpire美元);}$ end_time=microtime(真正);回声“花费时间:“。(end_time - start_time美元)。“\ n"

复述的最大并发量是多少