Browse Source

增加BloomFilter

zhou-hao 6 years ago
parent
commit
0626a57c71

+ 6 - 0
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-api/pom.xml

@@ -36,5 +36,11 @@
             <artifactId>spring-boot-starter</artifactId>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>20.0</version>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 </project>

+ 25 - 0
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-api/src/main/java/org/hswebframework/web/concurrent/counter/AbstractBoomFilterManager.java

@@ -0,0 +1,25 @@
+package org.hswebframework.web.concurrent.counter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author zhouhao
+ */
+public abstract class AbstractBoomFilterManager implements BloomFilterManager {
+
+    private final Map<String, BloomFilter> counterStore = new HashMap<>(128);
+
+    @Override
+    public BloomFilter getBloomFilter(String key) {
+        BloomFilter counter = counterStore.get(key);
+        if (counter != null) {
+            return counter;
+        }
+        synchronized (counterStore) {
+            return counterStore.computeIfAbsent(key, this::createBloomFilter);
+        }
+    }
+
+    protected abstract BloomFilter createBloomFilter(String name);
+}

+ 17 - 0
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-api/src/main/java/org/hswebframework/web/concurrent/counter/BloomFilter.java

@@ -0,0 +1,17 @@
+package org.hswebframework.web.concurrent.counter;
+
+import lombok.SneakyThrows;
+
+import java.util.function.Supplier;
+
+public interface BloomFilter {
+
+    boolean put(String unique);
+
+    @SneakyThrows
+    default void tryPut(String unique, Supplier<? extends Exception> supplier) {
+        if (!put(unique)) {
+            throw supplier.get();
+        }
+    }
+}

+ 6 - 0
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-api/src/main/java/org/hswebframework/web/concurrent/counter/BloomFilterManager.java

@@ -0,0 +1,6 @@
+package org.hswebframework.web.concurrent.counter;
+
+public interface BloomFilterManager {
+
+    BloomFilter getBloomFilter(String key);
+}

+ 22 - 0
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-api/src/main/java/org/hswebframework/web/concurrent/counter/GuavaBloomFilterManager.java

@@ -0,0 +1,22 @@
+package org.hswebframework.web.concurrent.counter;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.nio.charset.StandardCharsets;
+
+@Getter
+@Setter
+public class GuavaBloomFilterManager extends AbstractBoomFilterManager {
+
+    private long expectedInsertions = 5000L;
+
+    private double fpp = 0.01;
+
+    @Override
+    protected BloomFilter createBloomFilter(String name) {
+        com.google.common.hash.BloomFilter<String>
+                filter = com.google.common.hash.BloomFilter.create((str, sink) -> sink.putString(str, StandardCharsets.UTF_8), expectedInsertions, fpp);
+        return filter::put;
+    }
+}

+ 22 - 0
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-api/src/test/java/org/hswebframework/web/concurrent/counter/GuavaBloomFilterManagerTest.java

@@ -0,0 +1,22 @@
+package org.hswebframework.web.concurrent.counter;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class GuavaBloomFilterManagerTest {
+
+    @Test
+    public void testGuavaBloomFilter() {
+        BloomFilterManager manager = new GuavaBloomFilterManager();
+
+        BloomFilter filter = manager.getBloomFilter("test");
+        Assert.assertNotNull(filter);
+
+        Assert.assertTrue(filter.put("test"));
+        Assert.assertFalse(filter.put("test"));
+
+    }
+
+}

+ 20 - 0
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-redis/src/main/java/org/hswebframework/web/counter/redis/RedisBloomFilterManager.java

@@ -0,0 +1,20 @@
+package org.hswebframework.web.counter.redis;
+
+import lombok.AllArgsConstructor;
+import org.hswebframework.web.concurrent.counter.AbstractBoomFilterManager;
+import org.hswebframework.web.concurrent.counter.BloomFilter;
+import org.redisson.api.RBloomFilter;
+import org.redisson.api.RedissonClient;
+import org.redisson.client.codec.StringCodec;
+
+@AllArgsConstructor
+public class RedisBloomFilterManager extends AbstractBoomFilterManager {
+
+    private RedissonClient redissonClient;
+
+    @Override
+    protected BloomFilter createBloomFilter(String name) {
+        RBloomFilter<String> filter = redissonClient.getBloomFilter("hsweb:bloom-filter:" + name, StringCodec.INSTANCE);
+        return filter::add;
+    }
+}