java 共享内存使用

最近由于项目需要,需要考虑对内存进行一下优化。
背景:主要是有一个项目使用了mysql数据库和storm,为了匹配两者的速度,中间采用了缓存。原来的方法是本地进程自己缓存一份数据,由于数据比较多,使用了大量的内存不说,还导致比较严重的GC问题(主要由于缓存更新比较频繁,需要不断淘汰和添加数据),而且每一个进程还需要一个daemon线程去维护和定期更新缓存,种种原因导致资源消耗比较大,于是决定改造一下。
方案选择:1)改用现成的redis或者memorycache缓存 2)每台机器缓存一份,进程间共享
由于方案1有网络开销,并且组建redis集群有现实障碍(我们自己的问题),单一的redis或者memorycache可能会导致网络瓶颈和单点问题,因此没使用。
那就使用方案2,考虑进程间共享资源,那自然的方案是共享内存喽。


java共享内存的实现,唯一选择就是映像文件共享内存。先罗列下共享内存的特点:
1)可以被多个进程打开访问;
2)多个进程可以交替对某一共享内存执行写操作,不会导致数据一致性问题;
3)一个进程执行了内存的写操作后,不影响其他进程对该内存的访问,同时其他进程对更新后的内存具有可见性。
4)独占的写操作本身不会发生数据的一致性问题;
再来关注实现问题,java的NIO中MappedByteBuffer和FileChannel为我们实现共享内存提供了捷径。具体实现就不详细的写了,自己找吧
过程中遇到的几个问题:
1)映射到内存的大小,为了节省映射时间,固定每次映射到内存的块大小,采用4M或者128M,并且以链式串起来。具体函数
MappedByteBuffer java.nio.channels.FileChannel.map(MapMode mode, long position, long size) throws IOException
2) 对于数据的存放地址,需要根据块大小换算成线程地址,包括第几块和块内偏移,为了效率多用移位运算和与运算代替乘除法和取模操作
3)由于我们以缓冲为目的,自己实现了基于映射文件的线程安全的hashMap,便于快速查找和更新
对于这个问题,网上有现成的实现,主要考虑好冲突问题和内存回收问题就好,不是很复杂
4)为了保证数据一致性和简单,我们只有一个进程去更新共享内存,其余只读。并且在写入操作时,置正在写入标识,暂时阻塞读进程
标志位可以存在一个单独的小的映像文件共享内存中


@link 一些共享内存使用

http://tonybai.com/2013/03/18/sys-running-data-extraction-method-using-mmap/

http://www.ibm.com/developerworks/cn/aix/library/au-concurrent_boost/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值