solrlucene MMapDirectory报错深入分析总结.docx
《solrlucene MMapDirectory报错深入分析总结.docx》由会员分享,可在线阅读,更多相关《solrlucene MMapDirectory报错深入分析总结.docx(19页珍藏版)》请在冰豆网上搜索。
solrluceneMMapDirectory报错深入分析总结
1.Solr中MMapDirectory报错信息:
ERROR-2014-10-1108:
58:
15.114;mon.SolrException;null:
java.io.IOException:
Mapfailed
atsun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:
782)
atorg.apache.lucene.store.MMapDirectory.map(MMapDirectory.java:
283)
atorg.apache.lucene.store.MMapDirectory$MMapIndexInput.(MMapDirectory.java:
228)
atorg.apache.lucene.store.MMapDirectory.openInput(MMapDirectory.java:
192)
atorg.apache.lucene.store.NRTCachingDirectory.openInput(NRTCachingDirectory.java:
232)
atorg.apache.lucene.codecs.lucene41.Lucene41PostingsReader.(Lucene41PostingsReader.java:
72)
atorg.apache.lucene.codecs.lucene41.Lucene41PostingsFormat.fieldsProducer(Lucene41PostingsFormat.java:
430)
atorg.apache.lucene.codecs.perfield.PerFieldPostingsFormat$FieldsReader.(PerFieldPostingsFormat.java:
194)
atorg.apache.lucene.codecs.perfield.PerFieldPostingsFormat.fieldsProducer(PerFieldPostingsFormat.java:
233)
atorg.apache.lucene.index.SegmentCoreReaders.(SegmentCoreReaders.java:
127)
atorg.apache.lucene.index.SegmentReader.(SegmentReader.java:
56)
atorg.apache.lucene.index.ReadersAndLiveDocs.getReader(ReadersAndLiveDocs.java:
121)
atorg.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:
135)
atorg.apache.solr.core.SolrCore.execute(SolrCore.java:
1904)
atorg.apache.solr.servlet.SolrDispatchFilter.execute(SolrDispatchFilter.java:
659)
atorg.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:
362)
atorg.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:
158)
atcom.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:
188)
atcom.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:
116)
atcom.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:
77)
atcom.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:
908)
atcom.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:
997)
atcom.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.invokeFilters(DefaultExtensionProcessor.java:
1043)
atcom.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.handleRequest(DefaultExtensionProcessor.java:
963)
atcom.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.invokeFilters(DefaultExtensionProcessor.java:
1043)
atcom.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.handleRequest(DefaultExtensionProcessor.java:
963)
atcom.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:
3933)
atcom.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:
276)
atcom.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:
931)
atcom.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:
1583)
atcom.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:
186)
atcom.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:
445)
atcom.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:
504)
atcom.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:
301)
atcom.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:
262)
atcom.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:
214)
atcom.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCplete(NewConnectionInitialReadCallback.java:
113)
atcom.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:
165)
atcom.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:
217)
atcom.ibm.io.async.AsyncChannelFuture$1.run(AsyncChannelFuture.java:
205)
atcom.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:
1604)
Causedby:
java.lang.OutOfMemoryError:
Mapfailed
atsun.nio.ch.FileChannelImpl.map0(NativeMethod)
atsun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:
779)
...52more
2.解决方法:
Linux上虚拟内存配置
1)Linux上打开文件数和进程数配置
2)提高Oracle用户的shell限制
3)/etc/security/limits.conf
4)oraclesoftnproc2047
5)oraclehardnproc16384
6)oraclesoftnofile1024
7)oraclehardnofile65536
8)Ulimit配置虚拟内存等
在/etc/profile的最后面添加ulimit-sunlimited就可以了,source/etc/profile使修改文件生效,需要重启linux服务器生效。
参数介绍:
Ø-H设置硬件资源限制.
Ø-S设置软件资源限制.
Ø-a显示当前所有的资源限制.
Ø-csize:
设置core文件的最大值.单位:
blocks
Ø-dsize:
设置数据段的最大值.单位:
kbytes
Ø-fsize:
设置创建文件的最大值.单位:
blocks
Ø-lsize:
设置在内存中锁定进程的最大值.单位:
kbytes
Ø-msize:
设置可以使用的常驻内存的最大值.单位:
kbytes
Ø-nsize:
设置内核可以同时打开的文件描述符的最大值.单位:
n
Ø-psize:
设置管道缓冲区的最大值.单位:
kbytes
Ø-ssize:
设置堆栈的最大值.单位:
kbytes
Ø-tsize:
设置CPU使用时间的最大上限.单位:
seconds
Ø-vsize:
设置虚拟内存的最大值.单位:
kbytes
Ø-unumber:
设置用户最大进程数(maxuserprocesses)
9)Linux上max_map_count配置,
限制一个进程可以拥有的VMA(虚拟内存区域)的数量
Ø查看max_map_count值:
more/proc/sys/vm/max_map_count
vm.max_map_count=200000直接写到/etc/sysctl.conf中,然后执行sysctl-p
3.使用java实现MMapDirectory方法介绍
作为NIO的一个重要的功能,Mmap方法为我们提供了将文件的部分或全部映射到内存地址空间的能力,同当这块内存区域被写入数据之后[dirty],操作系统会用一定的算法把这些数据写入到文件中[这一过程java并没有提供API,后面会提到]。
这样我们实际上就获得了间接操纵内存的能力,而且内存与文件之间的同步是由操作系统完成的,不用我们额外操心。
也就是说,只要我们把内存数据块规划好[也就是实现一下C语言的SharedMemory功能],剩下的事情交给操作系统烦恼就好了。
我们既获得了高效的读写操作能力,又解决了数据的持久化问题,多么理想的功能啊!
但必须说明的是mmap毕竟不是数据库,不能很方便地提供事务功能、类似sql语句那样的查找功能,也不具备备份、回滚、迁移的能力,这些都要自己实现。
不过这样显然不如放在数据库里放心,所以我们的经验是特别重要的数据还是存数据库,不太重要的、但是又访问量很大、读写操作多且需要持久化功能的数据是最适合使用mmap功能的。
使用Java的mmapAPI代码框架如下所示:
(1)RandomAccessFileraf=newRandomAccessFile(File,"rw");
(2)FileChannelchannel=raf.getChannel();
(3)MappedByteBufferbuff=channel.map(FileChannel.MapMode.READ_WRITE,startAddr,SIZE);
(4)buf.put((byte)255);
(5)buf.write(byte[]data)
其中最重要的就是那个buff,它是文件在内存中映射的标的物,通过对buff的read/write我们就可以间接实现对于文件的读写操作,当然写操作是操作系统帮忙完成的。
4.linux上内存和虚拟内存
来源于:
第一层理解
1. 每个进程都有自己独立的4G内存空间,各个进程的内存空间具有类似的结构
2. 一个新进程建立的时候,将会建立起自己的内存空间,此进程的数据,代码等从磁盘拷贝到自己的进程空间,哪些数据在哪里,都由进程控制表中的task_struct记录,task_struct中记录中一条链表,记录中内存空间的分配情况,哪些地址有数据,哪些地址无数据,哪些可读,哪些可写,都可以通过这个链表记录
3. 每个进程已经分配的内存空间,都与对应的磁盘空间映射
问题:
计算机明明没有那么多内存(n个进程的话就需要n*4G)内存
建立一个进程,就要把磁盘上的程序文件拷贝到进程对应的内存中去,对于一个程序对应的多个进程这种情况,浪费内存!
第二层理解
1. 每个进程的4G内存空间只是虚拟内存空间,每次访问内存空间的某个地址,都需要把地址翻译为实际物理内存地址
2. 所有进程共享同一物理内存,每个进程只把自己目前需要的虚拟内存空间映射并存储到物理内存上。
3. 进程要知道哪些内存地址上的数据在物理内存上,哪些不在,还有在物理内存上的哪里,需要用页表来记录
4. 页表的每一个表项分两部分,第一部分记录此页是否在物理内存上,第二部分记录物理内存页的地址(如果在的话)
5. 当进程访问某个虚拟地址,去看页表,如果发现对应的数据不在物理内存中,则缺页异常
6. 缺页异常的处理过程,就是把进程需要的数据从磁盘上拷贝到物理内存中,如果内存已经满了,没有空地方了,那就找一个页覆盖,当然如果被覆盖的页曾经被修改过,需要将此页写回磁盘
总结:
优点:
1.既然每个进程的内存空间都是一致而且固定的,所以链接器在链接可执行文件时,可以设定内存地址,而不用去管这些数据最终实际的内存地址,这是有独立内存空间的好处
2.当不同的进程使用同样的代码时,比如库文件中的代码,物理内存中可以只存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了,节省内存
3.在程序需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用碎片。
另外,事实上,在每个进程创建加载时,内核只是为进程“创建”了虚拟内存的布局,具体就是初始化进程控制表中内存相关的链表,实际上并不立即就把虚拟内存对应位置的程序数据和代码(比如.text.data段)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫做存储器映射),等到运行到对应的程序时,才会通过缺页异常,来拷贝数据。
还有进程运行过程中,要动态分配内存,比如malloc时,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做相应设置,当进程真正访问到此数据时,才引发缺页异常。
补充理解:
虚拟存储器涉及三个概念:
虚拟存储空间,磁盘空间,内存空间
可以认为虚拟空间都被映射到了磁盘空间中,(事实上也是按需要映射到磁盘空间上,通过mmap),并且由页表记录映射位置,当访问到某个地址的时候,通过页表中的有效位,可以得知此数据是否在内存中,如果不是,则通过缺页异常,将磁盘对应的数据拷贝到内存中,如果没有空闲内存,则选择牺牲页面,替换其他页面。
mmap是用来建立从虚拟空间到磁盘空间的映射的,可以将一个虚拟空间地址映射到一个磁盘文件上,当不设置这个地址时,则由系统自动设置,函数返回对应的内存地址(虚拟地址),当访问这个地址的时候,就需要把磁盘上的内容拷贝到内存了,然后就可以读或者写,最后通过manmap可以将内存上的数据换回到磁盘,也就是解除虚拟空间和内存空间的映射,这也是一种读写磁盘文件的方法,也是一种进程共享数据的方法共享内存
5.linux上top命令使用方法
来源于:
简介
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。
top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止.比较准确的说,top命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表.该命令可以按CPU使用.内存使用和执行时间对任务进行排序;而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定.
下面详细介绍它的使用方法。
参数含义
top-01:
06:
48up1:
22,1user,loadaverage:
0.06,0.60,0.48
Tasks:
29total,1running,28sleeping,0stopped,0zombie
Cpu(s):
0.3%us,1.0%sy,0.0%ni,98.7%id,0.0%wa,0.0%hi,0.0%si
Mem:
191272ktotal,173656kused,17616kfree,22052kbuffers
Swap:
192772ktotal,0kused,192772kfree,123988kcached
PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND
1379root160797624561980S0.71.30:
11.03sshd
14704root1602128980796R0.70.50:
02.72top
1root1601992632544S0.00.30:
00.90init
2root3419000S0.00.00:
00.00ksoftirqd/0
3rootRT0000S0.00.00:
00.00watchdog/0
统计信息区前五行是系统整体的统计信息。
第一行是任务队列信息,同uptime命令的执行结果。
其内容如下:
01:
06:
48当前时间
up1:
22系统运行时间,格式为时:
分
1user当前登录用户数
loadaverage:
0.06,0.60,0.48系统负载,即任务队列的平均长度。
三个数值分别为1分钟、5分钟、15分钟前到现在的平均值。
第二、三行为进程和CPU的信息。
当有多个CPU时,这些内容可能会超过两行。
内容如下:
total进程总数
running正在运行的进程数
sleeping睡眠的进程数
stopped停止的进程数
zombie僵尸进程数
Cpu(s):
0.3%us用户空间占用CPU百分比
1.0%sy内核空间占用CPU百分比
0.0%ni用户进程空间内改变过优先级的进程占用CPU百分比
98.7%id空闲CPU百分比
0.0%wa等待输入输出的CPU时间百分比
0.0%hi:
硬件CPU中断占用百分比
0.0%si:
软中断占用百分比
0.0%st:
虚拟机占用百分比
最后两行为内存信息。
内容如下:
Mem:
191272ktotal物理内存总量
173656kused使用的物理内存总量
17616kfree空闲内存总量
22052kbuffers用作内核缓存的内存量
Swap:
192772ktotal交换区总量
0kused使用的交换区总量
192772kfree空闲交换区总量
123988kcached缓冲的交换区总量,内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖,该数值即为这些内容已存在于内存中的交换区的大小,相应的内存再次被换出时可不必再对交换区写入。
进程信息区统计信息区域的下方显示了各个进程的详细信息。
首先来认识一下各列的含义。
序号列名含义
aPID进程id
bPPID父进程id
cRUSERRealusername
dUID进程所有