为了提高服务器响应速度,服务器配置了8G内存,并把所有数据加载到静态变量,大约1G多的数据,
再加上运行期间的缓存等,服务器物理内存占用最高可以达到6个多G,
在运行时都会出现站点瞬间无响应的情况,后来压力测试了一下,发现每隔1分钟,就会内存回收一次,回收的时候,tps也跌到接近0,通过内存优化,现在内存占用最高跌到5G多,情况有所改善,但是依旧存在内存回收瞬间,站点就停止响应的问题请教这种问题如何避免呢?

解决方案 »

  1.   

    如果new一个对象的时候,这个对象的大小超过了85k,那么CLR就会把这个对象放在LOH上面。如果此时LOH的空间不足了,那么CLR就会启动垃圾回收器去扫描LOH堆和那个一般堆上面的第2代对象,我们之前说过,如果扫描第2代对象,就同时扫描第1代,第0代,那么实际相当于扫描了整个托管堆,性能影响可想而知。参考:http://www.cnblogs.com/yanyangtian/archive/2011/02/17/1956768.html
      

  2.   

    没有这么写的吧?1G的缓存放在内存中,这样子行吗?数据库也只提供不超过100M的缓存(oracle已经算很N的数据库了,好像只有几M),是不是换个思路啊?
      

  3.   

    我有这么大的内存,为什么不能用呢?
    走本地内存,总比还要经过TCPIP访问网络数据库快吧
      

  4.   


    数据量大,在内存里面查找到需要的数据花费的cpu很多的。通过网络访问数据库不会慢的。要知道,一个分布式XX管理系统的进行性能测试肯定比不过比较优秀的学生编写微型XX管理系统。因为分布式系统得经过复杂的算法,进行定位缓存在哪个服务器,经过了网络延迟,最后进入到服务器了还得调出缓存,返回数据,又经过网络延迟被应用程序得到。
    学生作业级别的微型系统,紧紧在本地操作而已,但是它负载能力肯定不如分布式这样复杂的系统。
      

  5.   

    这个木啥办法,毕竟iis这货回定期回收应用程序池,一旦回收了在重启必然又得重新加载你那些静态数据就像你说滴6G的数据加载完,那是受不了我想可以考虑二级缓存,可以考虑把缓存过程放到其他非iis服务中,可以考虑分拆开搞分布式缓存
      

  6.   

    忘记回来回复了,
    站点分拆为WCF进程和站点后,
    问题依旧存在,WCF进程依旧会进行GC二代扫描,造成进程挂起,从而站点的请求也被挂起,只不过分拆前是挂起IIS进程,
    分拆后,是IIS的请求被WCF进程挂起微软的GC有个通知机制,感觉不靠谱,
    GC.RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold)这两个参数的含义是指的是第2代中存活的对象个数和大对象堆中对象个数,满足这两个参数后,便会引发通知所以如果值设置太小,可能回收完毕,才收到通知;
    如果设置太大,可能收到通知后,很久才回收
      

  7.   


    求教,如何不回收?难道用C++写代码?
    我这边都是大量的Dictionary对象
      

  8.   


    求教,如何不回收?难道用C++写代码?
    我这边都是大量的Dictionary对象
    不用C++,也可以让他不回收。
      

  9.   

    说两点优化建议:
    1.所有的对象能用struct的就绝不要用class
    2.无论是Dictionary还是List,最好设置好Capacity
      

  10.   

    数据库中是加密的string数据
    现有C#写的解密的方法。如何做字段的内容搜索。各位有高招?
      

  11.   

     好像这个问题  我也刚遇到
     硬件配置比你高  6台1T 内存服务器 
     但数据量比你的高  加载数据一次吃掉20G 内存
     
     按照你的想法 都考虑进去 其实就是硬件提升  
     
     运行一套算法 如果生成20M 数据 当中会吃掉200M 左右内存 
     这是一个人的 缓存不会直接清掉  内存也不会马上释放 用的JAVA一套框架  如果是100个人 那就多少G了
     如果代码修改不了  只能提升硬件
      

  12.   

    还是搞清楚缓存该存什么东西吧!不要把缓存跟数据库混为一谈。如果你把内存当数据库用,就别提什么“回收”,你必须像保证你的数据库不被清除地一样保证内存中的所谓数据不会重启。所谓缓存,比如说有100G内容,有3000W条(不同种类的)记录,你也可能仅在内存中放10M、几千条记录而已。这才是缓存。
      

  13.   

    就算你有200G内存,你的缓存数据也是必要的时候才增加一条啊!怎么能一下子增加100W条?你明明仅访问 第一条数据,甚至第一条数据都没有访问时,就花时间去加载不知道什么时间才会全都访问到的另外100W条数据(而且你还无法保证在后台数据更新、也就是这些所谓缓存变成脏数据时立刻清除缓存),你的命中率是再怎么吹牛也是0%。这叫做缓存么?
      

  14.   

    看样子你这样设计,性能不升反降。
    你8g内存在服务器里面算是入门级的了,按你说你的站点一次加载1G,峰值有5~6G,为什么被称为垃圾,因为用不到所以称为垃圾,不同等级的垃圾回收策略不一样,如果你1G的东西时时刻刻在用,我不觉得你内存配置才8G机器的CPU够用。垃圾回收的条件
    前面2种情况是严重影响系统运行的,垃圾回收会采用比较高的回收策略,而我觉得你放的东西应该都会满足这个策略,所以怎么看你放进去的东西在你只有8G内存的服务器下始终会被快速回收。而影响垃圾回收的性能其中几个是:
    垃圾回收和性能
    看来你怎么写性能影响严重“若要回收对象,垃圾回收器必须停止应用程序的所有正在执行的线程。 在某些情况下,例如当应用程序检索数据或者显示内容时,完整垃圾回收可能会在关键时刻进行,而且可能会影响性能。”
    你垃圾回收性能也不好,所以你卡了如何避免? 你要么别怎么写,要么再加一台服务器做缓存服务器绕开。net的机制
      

  15.   

    这么大的缓存,直接靠IIS支撑,它挺难受的!
    我觉得,可以考虑用缓存组件。比如memcache之类的。
    但也不能把所有数据库数据都放缓存吧,比如可以每次只把登陆对象相关数据加载,过段时间定时清理。
      

  16.   

    感谢楼上各位的回复,
    说具体一些吧:
    我这边是一个搜索站点,
    1、通过程序把几百万的资源 标题和简介进行分词,保存在一个字典里,并序列化为文件
      字典是:Dictionary<分词, Dictionary<资源id, 条件数据>>
    2、搜索站点启动时加载并反序列化这个字典到一个静态变量
    3、站点搜索时,遍历当前分词的字典,比对条件,返回资源id列表
    4、程序定时把增量数据提交给站点,去刷新那个字典,以保证数据及时性现在的问题,就是站点频繁进行2代回收,实际回收的内存并不多,主要是因为扫描的数据量太大,主要的几个问题:
    1、能不能避免回收时扫描静态变量指向的所有引用?
    2、如果把字典放到Redis之类的内存服务器,就增加了网络交互量 和 网络的延时,所以才考虑放在内存里,另一个考虑就是这是个对内服务的接口,如果接口慢,就会导致其它产品慢,引起连锁反应
      

  17.   

    能用xml就用xml吧
    Dictionary只标识xml的路径