介绍
布隆过滤器是指通过维护一张散列表对数据进行校验从而快速判定该数据是否存在于表中。在实际应用场景中主要用于预防恶意缓存击穿,一般在频繁查询的场景下,若大量恶意数据强行进行查询则会导致数据库和服务器压力过大,所有在查缓存之前往往会查询一下布隆过滤器验证此数据是否是原数据库中存在的有效数据。
既然涉及到哈希算法就势必会有哈希碰撞,而碰撞结果往往会导致布隆过滤器的数据误判(将不存在的数据误判定为存在),我在这里选用哈希算法还需要很多优化,大家看个思路即可
思路
在这里首先模拟正常数据插入,先构建一个数据集合,将数据进行遍历存入哈希表中。随后用生成的恶意数据集合进行计算比较,筛选出合法数据。
代码实现
哈希节点类
exist表示节点数据是否存在,默认为false
info用于存储数据
private boolean exist = false;
private String info = "";
数据构造类
realData表示正常入参数据
checkData恶意入参数据
checkedData被布隆过滤器过滤后的数据
private List<String> realData;
private List<String> checkData;
private List<String> checkedData;
数据构造方法
在这里首先进行正常入参数据和恶意入参数据的构造,随机生成长度1~40的随机字符拼接为字符串数据,两个数组用相同方法构造
DataCreate(int real, int check){
checkedData = new ArrayList<>();
realData = new ArrayList<>();
checkData = new ArrayList<>();
createData(this.realData,real);
createData(this.checkData,check);
}
private void createData(List<String> list,int num){
Random r = new Random();
int word=0;
int length=0;
String info = "";
for(int i=0;i<num;i++){
length = 1+r.nextInt(40);
for(int j=0;j<length;j++){
word = 48+r.nextInt(78);
info +=(char)word;
}
list.add(info);
info="";
}
}
过滤器类
维护一个哈希节点数组
private hashPoint[] list;
哈希值为入参字符串拆解累加最后取余得到
private int getHashCode(String info){
int hashCode = 1;
char[] arr = info.toCharArray();
for(char i:arr){
hashCode = hashCode+(int)i;
}
return hashCode%this.list.length;
}
数据入参方法
正常数据导入并存入构造新的哈希节点进入列表
private void addInfo(String info){
int hashCode = getHashCode(info);
if(this.list[hashCode]==null){
this.list[hashCode] = new hashPoint(info,true);
}else{
this.list[hashCode].setInfo(this.list[hashCode].getInfo()+"&"+info);
}
}
检查方法
获取该字符串哈希值并传入比较
public boolean check(int num){
if(this.list[num]!=null){
if(this.list[num].isExist()){
return true;
}
}
return false;
}
误判数据检测
public List<String> checkWorng(List<String> checkedData){
List<String> worngInfos = new ArrayList<>();
int i = 0;
for(String s:checkedData){
i = getHashCode(s);
if(this.list[i].getInfo().indexOf(i)==-1){
worngInfos.add(s);
}
}
return worngInfos;
}
完整代码
哈希节点类
package BoolmFilter;
public class hashPoint {
private boolean exist = false;
private String info = "";
hashPoint(String info,boolean exist){
this.info = info;
this.exist = exist;
}
public boolean isExist() {
return exist;
}
public void setExist(boolean exist) {
this.exist = exist;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
过滤器类
package BoolmFilter;
import java.util.ArrayList;
import java.util.List;
public class Filter {
private hashPoint[] list;
Filter(){
list = new hashPoint[1000];
}
public hashPoint[] getHasPoint(){
return this.list;
}
private void addInfo(String info){
int hashCode = getHashCode(info);
if(this.list[hashCode]==null){
this.list[hashCode] = new hashPoint(info,true);
}else{
this.list[hashCode].setInfo(this.list[hashCode].getInfo()+"&"+info);
}
}
private int getHashCode(String info){
int hashCode = 1;
char[] arr = info.toCharArray();
for(char i:arr){
hashCode = hashCode+(int)i;
}
return hashCode%this.list.length;
}
public void addFromList(List<String> list){
for(String i:list){
addInfo(i);
}
}
public List<String> checkFromList(List<String> checkData,List<String> checkedData){
for(String i:checkData){
if(check(getHashCode(i))){
checkedData.add(i);
}
}
return checkedData;
}
public boolean check(int num){
if(this.list[num]!=null){
if(this.list[num].isExist()){
return true;
}
}
return false;
}
public List<String> checkWorng(List<String> checkedData){
List<String> worngInfos = new ArrayList<>();
int i = 0;
for(String s:checkedData){
i = getHashCode(s);
if(this.list[i].getInfo().indexOf(i)==-1){
worngInfos.add(s);
}
}
return worngInfos;
}
}
数据构造类
package BoolmFilter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class DataCreate {
private List<String> realData;
private List<String> checkData;
private List<String> checkedData;
DataCreate(int real, int check){
checkedData = new ArrayList<>();
realData = new ArrayList<>();
checkData = new ArrayList<>();
createData(this.realData,real);
createData(this.checkData,check);
}
private void createData(List<String> list,int num){
Random r = new Random();
int word=0;
int length=0;
String info = "";
for(int i=0;i<num;i++){
length = 1+r.nextInt(40);
for(int j=0;j<length;j++){
word = 48+r.nextInt(78);
info +=(char)word;
}
list.add(info);
info="";
}
}
public List<String> getRealData() {
return this.realData;
}
public List<String> getCheckData() {
return this.checkData;
}
public List<String> getCheckedData() {
return this.checkedData;
}
}
测试类
package BoolmFilter;
import java.util.List;
public class TestMain {
public static void main(String[] args){
DataCreate dataCreate = new DataCreate(1000,10000);
Filter filter = new Filter();
filter.addFromList(dataCreate.getRealData());
//check(filter.getHasPoint());
List<String> insertDatas = filter.checkFromList(dataCreate.getCheckData(), dataCreate.getCheckedData());
List<String> errorDatas = filter.checkWorng(insertDatas);
System.out.println("通过布隆过滤器数据:"+insertDatas.size());
System.out.println("误判数据:"+errorDatas.size());
}
public static void check(hashPoint[] list){
int cum = 0;
int num = 0;
int x = 1;
for(int i=0;i<list.length-1;i++){
if(list[i]==null){
System.out.println("哈希值:"+i+",数据:-------------");
cum++;
}else{
System.out.println("哈希值:"+i+",数据:"+ list[i].getInfo());
cum++;
num++;
}
if(cum==99){
System.out.println("第"+((cum+1)*x-99)+"至第"+((cum+1)*x)+"数据有"+num);
x++;
cum=0;
num=0;
}
}
}
}
测试结果
这个结果不是太满意,回头再优化吧
通过布隆过滤器数据:6307
误判数据:6082