Arp*_*sss 3 java hashmap key-value
我正在尝试为我们的服务器编写代码,我必须通过URL查找用户访问类型.
现在,在开始时,我们看到每天访问1亿个不同的URL.现在,到那时它每天变成近6亿个不同的URL.
对于1亿,我们所做的是:
1)使用并行数组构建HashMap,其键是URL的一部分(表示为LONG),值是URL的其他部分(表示为INT) - 键可以有多个值.
2)然后搜索HashMap以查找访问的URL时间.
现在,随着HashTable变得越来越大,我们所做的就是:
1)构建两个/三个单独的HashTable,并加载和存储它(在通用文件系统上)以查找URL访问的次数.
现在,问题是,
1)虽然HashTable性能相当不错,但是在加载/存储HashTable时代码需要更多时间(我们使用文件通道,加载/存储HashTable需要16-19秒 - 20000万条入口 - 因为加载因子是0.5)
我们要问的是:
1)如何解决这个问题?
2)如何减少加载/存储时间(我以前问过,但似乎文件通道是最好的方式)?
3)存储一个大的HashTable(超过内存)并重复缓存它将是一个很好的解决方案?如果是这样,怎么做(至少一些指针).我们尝试使用
RandomAccessFile raf = new RandomAccessFile("array.dat", "rw");
IntBuffer map = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1 << 30).order(ByteOrder.nativeOrder()).asIntBuffer();
Run Code Online (Sandbox Code Playgroud)
然而,比以前更糟糕的表现.
谢谢.
注意:
1)根据之前的Stack Overflow建议,我们使用一些像TokyoCabinet这样的NoSQL DB,但根据我们的经验,自定义HashTable比1亿个键值对提供更好的性能.
2)磁盘缓存的预读数据是不可能的,因为当系统启动时,我们的应用程序将开始工作,并在系统启动的第二天开始工作.
我们忘了提到的是:
1)由于我们的应用程序是项目的一部分并且应用于小型园区,因此我们假设访问的URL不超过8亿.因此,您可以认为600/700数据值是固定的.
2)我们主要关心的是表现.
3)我们必须在本地运行我们的应用程序.
最好将表作为内存映射缓冲区进行访问.这样,您可以简单地实现对文件的随机访问,而无需担心加载和存储,并将缓存留给操作系统.我看到你当前的实现已经使用内存映射访问进行读写,但它仍然会将内容加载到java堆中.避免这种数据重复和复制!将支持文件本身视为数据结构,只有在您需要时才访问它实际需要的部分.
在该文件中,如果您确实确定哈希冲突不是问题,那么哈希映射将起作用.否则我会在那里找到一个B +树,其节点大小与你的硬盘页面大小相同.这样,每个磁盘访问将产生比单个密钥更多的可用数据,从而导致更浅的树和更少的单个磁盘操作.
我猜其他人会实现这样的东西,但是如果你更喜欢自己的哈希映射实现,你可能也喜欢编写自己的内存映射B +树.