URL去重的六种方法
去重思路
在不考虑业务场景和数据量的情况下,我们可以使用以下的方案来实现URL的重复判断
- 使用java的Set集合,根据添加时的结果来判断url是否重复(添加成功表示URL不重复)
- 使用Redis中的Set集合,根据添加时的结果来判断URL是否重复
- 把数据库中的URL设置为唯一索引,根据添加时的结果来判断URL是否重复
- 使用Guava的布隆过滤器来实现URL判重
- 使用Redis的布隆过滤器来实现URL判重
接下来我们就分别分析下这六种判重的方法。
一、使用Java中Set集合
由于Set集合具有不可重复性,因此我们可以通过添加Set集合时的结果来盘点URL是否重复
public class URLRepeat {
// 待去重 URL
public static final String[] URLS = {
"https://blog.csdn.net/issunmingzhi",
"www.baidu.com",
"https://blog.csdn.net/issunmingzhi"
};
public static void main(String[] args) {
Set<String> set = new HashSet();
for (int i = 0; i < URLS.length; i++) {
String url = URLS[i];
boolean result = set.add(url);
if (!result) {
// 重复的 URL
System.out.println("URL 已存在了:" + url);
}
}
}
}
二、Redis Set 集合去重
思路和第一种基本一致,利用Set的不可重复性
// 待去重 URL
public static final String[] URLS = {
"https://blog.csdn.net/issunmingzhi",
"www.baidu.com",
"https://blog.csdn.net/issunmingzhi"
};
@Autowired
RedisTemplate redisTemplate;
@RequestMapping("/url")
public void urlRepeat() {
for (int i = 0; i < URLS.length; i++) {
String url = URLS[i];
Long result = redisTemplate.opsForSet().add("urlrepeat", url);
if (result == 0) {
// 重复的 URL
System.out.println("URL 已存在了:" + url);
}
}
}
以上代码中我们借助了Spring Data中的RedisTemplate实现,所以在Spring Boot项目中要引入
spring-boot-starter-data-redis
框架,配置信息如下:<!-- 添加操作 RedisTemplate 引用 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
然后再配置Redis的连接信息:
spring.redis.host=127.0.0.1 spring.redis.port=6379 #spring.redis.password=123456 # Redis 服务器密码,有密码的话需要配置此项
三、唯一索引去重
建表的时候创建唯一索引
四、Guava布隆过滤器去重
布隆过滤器,实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
我们可以借助Guava框架来操作布隆过滤器,首先先在pom.xml中添加Guava的引用
<!-- 添加 Guava 框架 -->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-jre</version>
</dependency>
URL判重代码
public class URLRepeat {
// 待去重 URL
public static final String[] URLS = {
"https://blog.csdn.net/issunmingzhi",
"www.baidu.com",
"https://blog.csdn.net/issunmingzhi"
};
public static void main(String[] args) {
// 创建一个布隆过滤器
BloomFilter<String> filter = BloomFilter.create(
Funnels.stringFunnel(Charset.defaultCharset()),
10, // 期望处理的元素数量
0.01); // 期望的误报概率
for (int i = 0; i < URLS.length; i++) {
String url = URLS[i];
if (filter.mightContain(url)) {
// 用重复的 URL
System.out.println("URL 已存在了:" + url);
} else {
// 将 URL 存储在布隆过滤器中
filter.put(url);
}
}
}
}
五、Redis布隆过滤器
除了 Guava 的布隆过滤器,我们还可以使用 Redis 的布隆过滤器来实现 URL 判重。在使用之前,我们先要确保 Redis 服务器版本大于 4.0(此版本以上才支持布隆过滤器),并且开启了 Redis 布隆过滤器功能才能正常使用。
Redis中,布隆过滤器的操作不多,主要包含以下几个:
- bf.add:添加元素
- bf.exists:判断某个元素是否存在
- bf.madd:添加多个元素
- bf.mexists:判断多个元素是否存在
- bf.reserve:设置布隆过滤器的准确率