java pfadd_hyperLoglog的使用

首先来说一下业务场景吧。

如果需要去统计某个行为,如请求的发起次数,用redis去模拟这个行为就是如下,使用一个key=request_1的键值对,来保存该请求的处理次数即可,自增模拟访问请求。如果针对多个请求的统计,使用多个键值对去保存即可。

127.0.0.1:6379> set request_1 0

OK

127.0.0.1:6379> INCR request_1

(integer) 1

127.0.0.1:6379> INCR request_1

(integer) 2

127.0.0.1:6379> INCR request_1

(integer) 3

127.0.0.1:6379> INCR request_1

(integer) 4

127.0.0.1:6379> INCR request_1

(integer) 5

127.0.0.1:6379> INCR request_1

(integer) 6

那么问题来了,如果是对某个用户对某个请求的次数去重呢?就是某个用户访问某个请求,历史只算一次,我们按简单的来的话,java里面的数据结构必然会想到set,因为去重。那么redis里面也有set。简单概括一下就是,总共有多少个客户访问了某个请求,如果用set的话,可以实现功能,对于小项目来说,客户数量不多,数据量也不会很庞大。是可行的。

但是对大项目来说呢?这个set只会无限扩张,最后变得很庞大,非常占用内存,变得很臃肿。

那么如何既能够实现该功能,又可以减少内存的浪费呢,可以考虑使用hyperLoglog

先来基本的使用一下(命令为什么是pf,因为作者的姓名简称就是Pf)

模拟对requset_1的浏览用户的添加

127.0.0.1:6379> PFADD request_1_users user1

(integer) 1

127.0.0.1:6379> PFADD request_1_users user2

(integer) 1

127.0.0.1:6379> PFADD request_1_users user3

(integer) 1

统计出requset_1的浏览用户数

127.0.0.1:6379> PFCOUNT request_1_users

(integer) 3

如果某天,需要知道哪些客户,既访问了请求1又访问了请求2怎么办?

这个时候还有一个很强大的功能PFMERGE,我们来模拟一下

127.0.0.1:6379> PFADD request_1_users user1

(integer) 1

127.0.0.1:6379> PFADD request_1_users user2

(integer) 1

127.0.0.1:6379> PFADD request_1_users user3

(integer) 1

127.0.0.1:6379> PFADD request_2_users user1

(integer) 1

127.0.0.1:6379> PFADD request_2_users user2

(integer) 1

127.0.0.1:6379> PFADD request_2_users user4

(integer) 1

127.0.0.1:6379> PFCOUNT request_1_users

(integer) 3

127.0.0.1:6379> PFCOUNT request_2_users

(integer) 3

127.0.0.1:6379> PFMERGE request_1_2_users request_1_users request_2_users

OK

127.0.0.1:6379> PFCOUNT request_1_2_users

(integer) 4

通过PFMERGE指令,可以将多个hyperLoglog合在一块,生成新的集合。request_1_users集合有user1,user2,user3 request_2_users有user1,user2,user4,所以最终去重合并后的集合数应该为4.

概括一下就是hyperLoglog具备了以下功能

1.pfadd 往集合添加成员

2.pfcount 统计集合的长度

3.pfmerge 将多个集合融合成一个新集合

特点:数量特别大的时候内存占用只有12k,远远小于set占用的内存,另外数量大的时候可能会存在较小误差(即实际上pfadd了一亿次,而pfcount的数量少于1亿,但是这俩个的值区别不会太大,待会验证一下)

那么我们通写代码的方式来使用一下

首先看看redisTemplate对hyperLoglog的支持,总共有几个方法,add,size,delete,union,添加,统计,删除,融合,基本的都支持了。

public interface HyperLogLogOperations {

/**

* 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. {@literal null} when used in pipeline /

* transaction.

*/

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 {@literal null} when used in pipeline / transaction.

*/

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}.

* @return {@literal null} when used in pipeline / transaction.

*/

Long union(K destination, K... sourceKeys);

/**

* Removes the given {@literal key}.

*

* @param key must not be {@literal null}.

*/

void delete(K key);

}

直接上代码

@Component

public class HyperLoglogUtils {

@Autowired

private RedisTemplate jedisTemplate;

public Long add(String key, String ... value) {

return jedisTemplate.opsForHyperLogLog().add(key, value);

}

public void del(String key) {

jedisTemplate.opsForHyperLogLog().delete(key);

}

public Long merge(String destination, String ...sourceKeys) {

return jedisTemplate.opsForHyperLogLog().union(destination, sourceKeys);

}

public Long count(String key) {

return jedisTemplate.opsForHyperLogLog().size(key);

}

}

下面校验一下误差

public class TestHyperLoglog extends TestApplication{

@Autowired

private HyperLoglogUtils hyperLoglogUtils;

@Test

public void add() {

for(int i = 0; i < 100000; i ++) {

hyperLoglogUtils.add("my_req_one", "user" + i);

}

System.out.println(hyperLoglogUtils.count("my_req_one"));

}

}

最终输出结果99725 误差还是可以接受的,千分之225

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Wireshark是一款开源的网络协议分析工具,支持Windows、Linux和Mac等多个操作系统。它可以捕获和分析网络数据包,帮助用户了解网络通信的细节,包括协议、数据流和错误等。 Java_Wireshark是一个Java编写的Wireshark插件,可以在Wireshark中使用Java代码来处理捕获的数据包。使用Java_Wireshark需要先安装Wireshark和Java,在Wireshark的插件管理中添加Java_Wireshark插件,然后在Java_Wireshark中编写自己的处理逻辑。 下面是一个简单的Java_Wireshark示例,用于计算HTTP请求的数量: ```java import org.wireshark.api.*; import org.wireshark.api.annotations.*; import org.wireshark.api.plugins.*; @WiresharkPlugin(name = "HTTP Request Counter") public class HttpRequestCounter implements IPlugin { private int requestCount = 0; @Override public void run(final IPluginContext context) { final IPacketListener listener = new IPacketListener() { @Override public void onPacket(final IPacket packet) { if (packet.hasProtocol("HTTP")) { requestCount++; System.out.println(String.format("HTTP requests: %d", requestCount)); } } }; context.addPacketListener(listener); } } ``` 这个例子中,我们使用了Wireshark提供的IPacketListener接口来监听捕获的数据包,判断是否包含HTTP协议,并统计请求的数量。通过Wireshark的插件管理,我们可以将这个插件加载到Wireshark中,然后使用它来分析HTTP请求。 需要注意的是,Java_Wireshark是一个比较高级的功能,需要一定的Java编程经验和Wireshark的使用经验。如果您不熟悉Java和Wireshark,建议先学习基础知识再尝试使用Java_Wireshark。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值