本文博客地址1. 系统级锁定支持:
memcache客户端不支持锁相关的功能,而服务端又支持并发,这样其实就会带来数据混乱的问题,我们之前的做法是实现一个应用层的锁:   1. <?php  
   2. /** 
   3.  * author: selfimpr 
   4.  * blog: http://blog.csdn.net/lgg201 
   5.  * mail: [email protected] 
   6.  */  
   7. $m = new Memcache();  
   8. $m->addServer(......);  
   9. //锁定  
  10. function lock($m, $key, $timeout = 5000, $wait = 15) {  
  11.   while($i ++ <= $wait && false !== $m->get('lock_'.$key));  
  12.   return false === $m->get('lock_'.$key) && ($m->set('lock_'.$key, $timeout));  
  13. }  
  14. //解锁  
  15. function unlock($m, $key) {  
  16.   return $m->delete('lock_'.$key);  
  17. }  
  18. ?>  
上面的方式构建锁定与解锁方法,然后在需要锁定的地方,get前加锁,set后解锁。
上面的解决方法,会降低并发导致的数据混乱问题,但不能根治,因为我们在lock的时候可能会是并发的,同时拿到了锁。。
后来,考虑过应用层实现的乐观锁机制,不过没有应用起来,也就不了了之了。。
最近换了Memcached客户端,发现其中支持cas这个方法,其实就是一个系统层的乐观锁。   1. <?php  
   2. $m = new Memcached();  
   3. $m->addServer(....);  
   4. $value = $m->get($key, $cas);  
   5. //业务操作  
   6. $m->cas($cas, $key, $value);  
   7. ?>  
get的时候,传一个$cas参数,Memcached::get这个方法在定义的时候,$cas是一个引用参数,执行完后,$cas这个名字已经被修改为memcached服务端返回的一个唯一标识了。
当我们set这个key的时候,带上这个cas值,以cas接口设置过去,服务端就能根据cas值判断该key对应的值是否被修改过,如果被修改过,说明是脏数据,向客户端发送错误消息。
由于这个锁定的验证机制是memcached的服务端提供的,因此,我们可以相信它的正确性。2. 获取Memcached中的所有的key
这个在memcache扩展中支持,Memcached扩展中反而不支持。
使用的方法是Memcache::getExtendedStats(....),三个参数,这个这里就不写了,php-memcache文档翻译的时候,我会加进去。
顺便提下,有精力有时间的朋友请参与支持:http://code.google.com/p/phpdoc-zh/,PHP官方文档翻译,公益项目3. 持久化连接问题
Memcache客户端是支持持久化连接的,而Memcached客户端不支持持久化连接,并且Memcached客户端在释放连接的时候本身可能有bug,在高并发的情况下会导致Memcached服务端大量的连接处于time_wait状态无法释放。。这样就会导致一部分请求失败。。
我们使用的是memcache作为session的handler,因为这个问题导致我们的session无法取到,客户端丢失连接,问题是比较严重的。最终从网上找到了解决方案就是修改Memcached服务端的socket释放相关的配置,我们进行的是如下修改:
修改文件:/etc/sysctl.cnf,加入或修改下面两个配置
net.ipv4.tcp_tw_recycle=1 //回收time_wait状态的socket
net.ipv4.tcp_fin_timeout=3 //认为的超时时间
然后/sbin/sysctl -p把这个文件reload一下
这个配置的修改,在网上有一位朋友使用apache的ab做过并发测试
1000000请求30000并发,没有出现Memcached的连接失败问题。
呵呵,这几天了解到的就这么多,有不足之处或错误的地方,还望指正。
谢谢