点击查看全文java
1.计算出key的哈希值。
2. 根据hash值和固定段大小取模计算出偏移位offset。
3. 根据固定前置+hash值/固定段大小计算出所处段的bitKey。
4. 根据bitKey和offset判断是否存在。
5. 若是存在而后调用containsFromDb判断是否存在。
6. 将redis setbit进行分段能够避免单个key数据量过大。
7. 若是redis是集群也能够将分出来的段根据jedis crc16算法有几率的被打算
在各个节点上,避免单个节点过热。redis
代码示例:
package six.com.crawler.work.space;算法
import java.util.Objects;数据库
import redis.clients.jedis.Jedis;分布式
public class RedisAndDbBloomFilter {ui
private String nameSpace; private Jedis jedis; private int fixSize; public RedisAndDbBloomFilter(String nameSpace,Jedis jedis,int fixSize){ this.nameSpace=nameSpace; this.jedis=jedis; this.fixSize=fixSize; } private int getHash(String key){ return key.hashCode(); } private void addToDb(int hash,String key){ //TODO 将记录保存至db } private boolean containsFromDb(int hash,String key){ //TODO 根据 hash key 查询数据库是否存在 return false; } /** * 根据hash和fixSize 算出bitKey * @param hash * @return */ private String getBitKey(int hash){ int bitKeyIndex=hash/fixSize; String bitKey=nameSpace+bitKeyIndex; return bitKey; } /** * 判断给定的key是否存在 * @param key * @return */ public boolean contains(String key){ //TODO 若是是集群模式这里须要分布式锁,若是是单机这里须要线程锁 Objects.requireNonNull(key, "the key must not be null"); int hash=getHash(key); int offset=hash%fixSize; String bitKey=getBitKey(hash); Boolean result=jedis.getbit(bitKey,offset); if(result.booleanValue()&&containsFromDb(hash, key)){ return true; } return false; } /** * 根据给定的key添加一个过滤记录 * @param key */ public void addRecord(String key){ //TODO 若是是集群模式这里须要分布式锁,若是是单机这里须要线程锁 int hash=getHash(key); int offset=hash%fixSize; String bitKey=getBitKey(hash); jedis.setbit(bitKey,offset, true); addToDb(hash, key); }
}this
点击查看全文url