浅谈海量数据处理

一、海量数据
所谓海量数据处理,无非就是基于海量数据上的存储、处理、操作。何谓海量,就是数据量太大,所以导致要么是无法在较短时间内迅速解决,要么是数据太大,导致无法一次性装入内存。
二、海量数据常见的解决方式
1.分而治之/hash映射 + hash统计 +堆/快速/归并排序;
2.双层桶划分
3.Bloom filter/Bitmap;
4.Trie树/数据库/倒排索引;
5.外排序;
6.分布式处理之Hadoop/Mapreduce。
三、应用举例
(1)海量日志数据,提取出某日访问百度次数最多的那个IP。
算法思想:分而治之+Hash
1.IP地址最多有2^32=4G种取值情况,所以不能完全加载到内存中处理;
2.可以考虑采用“分而治之”的思想,按照IP地址的Hash(IP)%1024值,把海量IP日志分别存储到1024个小文件中。这样,每个小文件最多包含4MB个IP地址;
3.对于每一个小文件,可以构建一个IP为key,出现次数为value的Hash map,同时记录当前出现次数最多的那个IP地址;
4.可以得到1024个小文件中的出现次数最多的IP,再依据常规的排序算法得到总体上出现次数最多的IP;
(2)有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
方案:顺序读文件中,对于每个词x,取hash(x)%5000,然后按照该值存到5000个小文件(记为x0,x1,…x4999)中。这样每个文件大概是200k左右。
如果其中的有的文件超过了1M大小,还可以按照类似的方法继续往下分,直到分解得到的小文件的大小都不超过1M。
对每个小文件,统计每个文件中出现的词以及相应的频率(可以采用hash_map),并取出出现频率最大的100个词(可以用含100个结点的最小堆),并把100个词及相应的频率存入文件,这样又得到了5000个文件。下一步就是把这5000个文件进行归并(类似与归并排序)的过程了。
(3)给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
方案:可以估计每个文件的大小为5G×64=320G,远远大于内存限制的4G。所以不可能将其完全加载到内存中处理。考虑采取分而治之的方法。
遍历文件a,对每个url求取hash(url)%1000,然后根据所取得的值将url分别存储到1000个小文件(记为a0,a1,…,a999)中。这样每个小文件的大约为300M。
遍历文件b,采取和a相同的方式将url分别存储到1000小文件(记为b0,b1,…,b999)。这样处理后,所有可能相同的url都在对应的小文件(a0vsb0,a1vsb1,…,a999vsb999)中,不对应的小文件不可能有相同的url。然后我们只要求出1000对小文件中相同的url即可。
求每对小文件中相同的url时,可以把其中一个小文件的url存储到hash_set中。然后遍历另一个小文件的每个url,看其是否在刚才构建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。
四、练习

public class TestHashMapDemo {
    //请随机10000个整数,放在LinkedList的里面  0-200之间的随机数
    //请问:如何快速的找出重复次数最多的一个?重复了几次
    //请问:如何快速的找出重复次数最多的前10个?分别重复了几次
    @Test
    public void testHashMap(){
        LinkedList<Integer> list=new LinkedList<Integer>();
        for(int i=0;i<10000;i++){
            list.add((int)(Math.random()*200)); 
        }
        LinkedHashMap<Integer, Integer> hashMap = new LinkedHashMap<Integer, Integer>();

        for(Integer key:list){
            Integer value=hashMap.get(key);
            if(value==null){
                hashMap.put(key, 1);
            }
            else{
                hashMap.put(key, value+1);  
            }
        }   
        Integer max=0;
        Integer key=null;
        Iterator<Entry<Integer, Integer>> it = 
                hashMap.entrySet().iterator();
        while(it.hasNext()){
            Entry<Integer,Integer> entry = it.next();
            Integer max1 =entry.getValue();
            Integer key1= entry.getKey();
            if(max1.compareTo(max)>0){
                max=max1;
                key=key1;       
            }   
        }
        System.out.println("重复次数最多的是"+key+"重复了多少次:"+max);

     }



    @Test
    public void testHashMapMaxTen(){
        LinkedList <Integer> list=new LinkedList<Integer>();

        for(int i=0;i<10000;i++){
            list.add((int)(Math.random()*200));
        }
        LinkedHashMap<Integer, Integer> hashMap = new LinkedHashMap<Integer, Integer>();
        for(Integer key:list){
            Integer value=hashMap.get(key);
            if(value==null){
                hashMap.put(key, 1);
            }
            else{
                hashMap.put(key, value+1);  
            }
        }
        PriorityQueue<Entry<Integer,Integer>> queue=new PriorityQueue<Entry<Integer,Integer>>
        (10, new Comparator<Entry<Integer,Integer>>(){
            public int compare(Entry<Integer,Integer> q1,Entry<Integer,Integer> q2){
                return (q1.getValue().compareTo(q2.getValue())>0)?1:(q1.getValue().compareTo(q2.getValue())==0?0:-1);

            }   
        });
        Iterator<Entry<Integer, Integer>> it = 
                hashMap.entrySet().iterator();
        int count=0;
        while(it.hasNext()){
            Entry<Integer,Integer> entry = it.next();
            count++;
            if(count<=10){
                queue.add(entry);
            }
            else{
                Integer data=queue.peek().getValue();  //peek返回头部元素
                if(entry.getValue().compareTo(data)>=0){
                    queue.remove();
                    queue.add(entry);
                }
            }
       }
        while(!queue.isEmpty()){
            Entry<Integer, Integer> data= queue.peek();
            System.out.print("key:"+data.getKey()+" "+"value:"+data.getValue());

            System.out.println();
            queue.poll();
            }       
      }
}

猜你喜欢

转载自blog.csdn.net/xd_fybdw/article/details/81113103