高并发下资源池资源申请一点思考

    技术2022-05-12  22

             昨天在看Cache Client代码的时候,发现在从资源池中获取SocketIO部分代码在高并发情况下效率不高,因此考虑通过一些变通的方式来提高效率,下面说的内容仅仅是当前自己琢磨出来可以部分提高效率的方法,希望看了这篇文章的同学能够有更好的方式或者算法来提高效率。

     

    情景:

           Cache Client SocketIO资源池是一个两级的Map,具体定义为:ConcurrentMap<String, ConcurrentMap<SockIO, Integer>>。第一级MapHost作为Key,第二级MapSockIO本身作为Key,三种SockIO状态(可用,占用,废弃)作为value。之所以采用一个Pool来存储三种状态主要是考虑到在高并发下,多个池之间保持原子性的复杂。

    每一次获取可用的SocketIO的操作需要经历:1.遍历Host所在的Map2.逐个比较状态。3.原子方法获取可用SocketIO。(并发问题所要求的,具体代码可以下载:http://memcache-client-forjava.googlecode.com/files/alisoft-xplatform-asf-cache-2.5.1-src.jar )。

    在修改过去的版本里面,首先遍历的过程是一个固定顺序的过程(keyset),这样会导致在高并发的情况下,越来越多的资源申请命中率会下降,因为压力总是落在keyset靠前的那些SockIO上(重复比较)。需要考虑通过什么手段可以提高在高并发下的申请命中率。

     

    思考:

    1.  资源申请的越早,被释放的可能性越高,因此是否可以考虑采用更新SockIO最后申请时间来作为后续申请的初步依据。(本身复杂度带来的耗时可能会超过命中率降低带来的损耗)

    2.  采用随机数的方式来确定keyset的起始游标,也就不是每次都从keyset第一位开始(可以把keyset看作一个首尾相接的数组)。

    3.  在每次资源回收的时候纪录下该资源为可用(当前为每一个Host就记录一个可能可用的资源,简单化操作),作为申请的首选尝试。(尝试不成功在去遍历)。

     

    当前实现了2,3组合,发现效果明显,在500个并发下,每个线程200次操作(一系列动作),压力测试结果如下:

    Cache test consume(cache测试总共耗时)average boundle consume(每个线程总耗时),average per request(每个线程每次操作总耗时)

     

    没有作任何改动以前的测试结果:

    cache test consume: 11507741, average boundle consume: 57538, average per request :115

     

    采用了2策略以后的测试结果:

    cache test consume: 10270512, average boundle consume: 51352, average per request :102

     

    采用了23策略以后的测试结果:

    cache test consume: 9140660, average boundle consume: 45703, average per request :91


    最新回复(0)