关于Memcached的CAS和Set方法造成Socket泄漏的问题

本文探讨了在使用Memcached的单线程场景下出现的Weblogic进程句柄数不断增长的问题。通过分析,发现问题源于Memcached的Set方法在特定情况下可能导致socket连接非正常关闭,进而引发句柄泄露。将Set方法替换为CAS方法后,问题得以解决。

    为了解决多并发下写Memcached的冲突方案,我们项目组引入了CAS机制。类同于Java并发包中的CAS(Compareand set)原子操作,用来处理同一个Item被多个线程更改的并发问题。Memcached的CAS是原理是引入版本概念,每一个存储数据对象都有一个64bit长度的数值作为该key相应value的版本。详细使用代码例如以下:

// 此方法不同于get方法 获取MemcachedItem对象
MemcachedItem item = mc.gets(key);
mc.cas(key, item.getValue() + String.valueOf(sleep), item.getCasUnique());

   在项目中对于单线程的场景。我们就使用了Memcached的Set方法。可是在项目耐久性測试过程中,我们发现站点后台管理server的Weblogic进程的句柄数在不断的添加。在Weblogic进行安全备份时,触发了一错误,并造成兴许的线程都Too many open files了。

相关错误信息例如以下:

<2015-5-30 下午11时05分16秒 CST> <Critical> <EmbeddedLDAP> <BEA-000000> <java.io.FileNotFoundException: /weblogic/Oracle/Middleware/user_projects/domains/shch_domain1/servers/shchbdf1/data/ldap/backup/EmbeddedLDAPBackup.zip (Too many open files)
       at java.io.FileOutputStream.open(Native Method)
       at java.io.FileOutputStream.<init>(FileOutputStream.java:194)
       at java.io.FileOutputStream.<init>(FileOutputStream.java:84)
       at com.octetstring.vde.backend.standard.BackupTask.runTask(BackupTask.java:55)

我们通过命令检查了未关闭的句柄,详细未关闭的句柄例如以下。我们知道socke通讯中can’t identify protocol是因为server异常中断socket通讯后,并未通知client。造成的client句柄不释放。



    我们知道应用和Memcached直接的通讯是使用NIO的Socket通讯。socket是连接是会产生句柄数的。可是正常关闭通道。句柄是会释放的。除非socket通道被非正常关闭。

从这个角度出发,我们对项目代码和异常场景进行了梳理。首先,仅仅有后台管理的进程会产生句柄数添加。而前台的集群报价系统多台server上都未发生这样的情况。

分析后台管理代码,有一个定时任务去定时更新Memcached的值,由于是单线程,使用的是Set方法。

可是这个set方法和报价的CAS方法都是对通过值进行改动,依据直觉推断是set方法和CAS方法在同一时候对一个值进行改动时,假设正好同一时候触发了,set方法的改动不成功。Memcached自己主动断开set值得连接,而未通知client,造成socket泄漏。

我们把Memcached的Set方法改动成CAS后。问题解决。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值