redis的HyperLogLog實戰

本文主要研究一下redis的HyperLogLog的用場html

相關命令

pfadd

每添加一個元素的複雜度爲O(1)java

127.0.0.1:6379> pfadd uv0907 uid1 uid2 uid3
(integer) 1
  • 添加元素到HyperLogLog中,若是內部有變更返回1,沒有返回0

pfcount

做用域單個HyperLogLog時,複雜度爲O(1),做用於多個HyperLogLog時,複雜度爲O(N)redis

127.0.0.1:6379> pfcount uv0907
(integer) 3
  • 返回該HyperLogLog的近似基數,若是是指定多個HyperLogLog則返回的是他們的並集的近似基數

pfmerge

複雜度爲O(N),N爲合併後的HyperLogLog數量算法

127.0.0.1:6379> pfadd uv0906 uid1 uid4 uid5
(integer) 1
127.0.0.1:6379> pfmerge uv0607 uv0906 uv0907
OK
127.0.0.1:6379> pfcount uv0607
(integer) 5
  • 合併指定的HyperLogLog到新的HyperLogLog中

使用場景

HyperLogLog是Probabilistic data Structures的一種,這類數據結構的基本大的思路就是使用統計機率上的算法,犧牲數據的精準性來節省內存的佔用空間及提高相關操做的性能。最典型的使用場景就是統計網站的每日UV。實例以下:segmentfault

@Test
    public void testUv(){
        String uv1 = "uv96";
        String uv2 = "uv97";
        IntStream.rangeClosed(1,100)
                .forEach(i -> {
                    System.out.println(i);
                    redisTemplate.opsForHyperLogLog()
                            .add(uv1,"user"+i);
                    redisTemplate.opsForHyperLogLog()
                            .add(uv2,"user"+i/2);
                });

        long uv1Count = redisTemplate.opsForHyperLogLog().size(uv1);
        System.out.println(uv1Count);
        long uv2Count = redisTemplate.opsForHyperLogLog().size(uv2);
        System.out.println(uv2Count);

        String uv1uv2 = "uv67";
        Long uv1uv2Count = redisTemplate.opsForHyperLogLog().union(uv1uv2,uv1,uv2);
        System.out.println(uv1uv2Count);
        Long realCount = redisTemplate.opsForHyperLogLog().size(uv1uv2);
        System.out.println(realCount);
    }

小結

  • redis的HyperLogLog特別是適合用來對海量數據進行unique統計,對內存佔用有要求,並且還可以接受必定的錯誤率的場景。
  • 對於union操做因爲是O(N),在海量數據層面須要注意慢查詢問題。

doc

相關文章
相關標籤/搜索