关于大数据去重的一些总结

关于大数据去重的一些总结

前言

之前在实习的公司里, 涉及到从 Hbase 中去数据转储到 MongoDB 这一过程, 其中取数据的依据是 redis 中存放的 id 队列, 因为往这个队列中生产ID完全是另一个项目组的行为, 在这一过程中当然会涉及到数据重复的问题, 针对这一问题, 当时项目中的做法是: 利用 redis 中 HyperLoglog 这一数据结构来去重.

HyperLoglog

Redis HyperLogLog是一种使用随机化的算法,以少量内存提供集合中唯一元素数量的近似值。

定义

A HyperLogLog is a probabilistic data structure used in order to count unique things (technically this is referred to estimating the cardinality of a set). Usually counting unique items requires using an amount of memory proportional to the number of items you want to count, because you need to remember the elements you have already seen in the past in order to avoid counting them multiple times. However there is a set of algorithms that trade memory for precision: you end with an estimated measure with a standard error, in the case of the Redis implementation, which is less than 1%. The magic of this algorithm is that you no longer need to use an amount of memory proportional to the number of items counted, and instead can use a constant amount of memory! 12k bytes in the worst case, or a lot less if your HyperLogLog (We’ll just call them HLL from now) has seen very few elements.

译: 一个HyperLogLog是一个用于统计唯一性事物数量的概率性数据结构(专业的说这叫估算集合的基数)。通常统计总数需要消耗与数量成正比例的存储空间,为了避免重复统计一个项多次你需要把你已经统计过的项记录下来,然而存在一种算法,损耗一定的精确度来节省存储空间,用一种带有一定误差的估算方式,在redis的实现中,这种误差小于1%。这种算法的魔力在于,你不再需要使用和已存储元素的数目成比例的存储空间,取而代之只使用固定数目的内存,在最差的情况下也仅仅需要12Kb的内存!如果你的元素数目很少,消耗的内存会更少。

HyperLogLog 可以接受多个元素作为输入,并给出输入元素的基数估算值:

  • 基数:集合中不同元素的数量。比如 {‘apple’, ‘banana’, ‘cherry’, ‘banana’, ‘apple’} 的基数就是 3 。
  • 估算值:算法给出的基数并不是精确的,可能会比实际稍微多一些或者稍微少一些,但会控制在合理的范围之内。

示例

> pfadd salary "12K"
(integer) 1

> pfadd salary "12K"
(integer) 0

> pfadd salary "13K"
(integer) 1

> pfadd salary "15K"
(integer) 1

> pfcount salary
(integer) 3

The commands prefix is “PF” in honor of Philippe Flajolet

RedisTemplate 中的接口

public interface HyperLogLogOperations<K, V> {

    /**
     * Adds the given {@literal values} to the {@literal key}.
     * 
     * @param key must not be {@literal null}.
     * @param values must not be {@literal null}.
     * @return 1 of at least one of the values was added to the key; 0 otherwise.
     */
    Long add(K key, V... values);

    /**
     * Gets the current number of elements within the {@literal key}.
     * 
     * @param keys must not be {@literal null} or {@literal empty}.
     * @return
     */
    Long size(K... keys);

    /**
     * Merges all values of given {@literal sourceKeys} into {@literal destination} key.
     * 
     * @param destination key of HyperLogLog to move source keys into.
     * @param sourceKeys must not be {@literal null} or {@literal empty}.
     */
    Long union(K destination, K... sourceKeys);

    /**
     * Removes the given {@literal key}.
     * 
     * @param key must not be {@literal null}.
     */
    void delete(K key);

}

在具体的项目中判重的作法是使用 add(K key, V... values) 方法时, 如果返回值为0 , 即添加的该值在队列中已存在.

当然, 使用HyperLoglog结构还是存在误差的, 我们应该将它应用在精确性不是很严格的场景下

其他的基数统计方法

bitmap

布隆过滤器

参考: https://blog.csdn.net/firenet1/article/details/77247649

你可能感兴趣的:(关于大数据去重的一些总结)