zoukankan      html  css  js  c++  java
  • 简化布隆过滤器——BitMap

    简化布隆过滤器——BitMap

    前言

    前段开发项目试就发现,一部分的代码实现存在着一些性能上的隐患。但当时忙于赶进度和由于卡发中的不稳定因素,想了许多解决方案也没有机会实施。最近,正好趁个机会进行一系列的改进。

    我在团队开发中负责开发服务器端。所以在编写业务逻辑层时,常常遇到以下这样的业务逻辑:
    1. 判断一个用户是否为在自己的好友列表中
    2. 判断一条动态是否已被用户翻阅
    3. 判断两个用户的标签的匹配度
    4. .....等等
    这些情况,我之前的方案是采用数据库来解决,为每条记录添加标记,需要查询时则遍历返回相应的集合

    但是随着用户量的不断增多、各个用户之间的关系不断地增加、以及用户使用软件的一系列行为中这些情况是非常频繁的,这样频繁遍历大量的记录的读操作会给数据库带来难以承受的压力。

    那么如何需找一种更好的解决方案?
    既能减少数据库需要遍历的记录数量且快速索引,又能用少量的内存表示大量的数据。
    其实如果我们对这一类型的业务逻辑进行抽象,可以得到:本质上就是判断一个元素是否存在于集合中
    所以我们可以采用位数组,通过数组的下标能快速地定位某个元素,用bit表示相应的内容能够节省大量的空间。

    但是这样结构依旧不够完美,如果数据量相对较少,数组中会存在大量的无用数据, 如长度为1024的byte数组中的只有少量位被表示为1,大量位依然是0。
    此时我们可以采用游程编码压缩byte数组。如上图的游程编码后的结果可以表示为[3, 0, 2, 0, 2, 0, 1, 0 ]

    一、Bitmap介绍

    Bitmap:被设计为一种用bit数组来储存表示2种状态紧凑、快速索引的数据结构(当然Java的util包中也实现这类型的数据结构—BitSet(不过并不是Set))

    二、BitMap主要原理

    其实说开来,Bitmap就是一个位数组而已,有着快速访问优势(下标访问),以及极小占用(用1bit来表示)

    三、BitMap的主要设计

    有点美中不足的是,Java中并没有提供bit这样的数据类型,即便是最小的数据类型byte也要占用8bit。这样就需要进行一些位运算来完成相应的操作,使得代码变得稍微复杂。
    1. BitMap的内部通过byte数组实现
    2. BitMap的基本操作:增删改查

       
     void  Set(int  position);		/* 将某位置"1" */
    boolean Get(int position); /* 判断某位的值 */
    void Clear(int postion); /* 将某位置"0" */

    Set()的实现原理

    废话不多说,直接看图

    主要分为两个步骤:
    1. 先将一个byte类型的”1”左移4位,得到结果
    2. 再进行简单的或运算,得到结果并覆盖原来的值

    Get()的实现原理


    理解了上面的例子,相信这个应该就很简单了
    同样是两步:
    1. 先将一个byte类型的”1”左移3位,得到结果
    2. 再进行与操作,得到结果并覆盖原来的值

    或许这里会有些疑问,为什么不考虑用boolean?
    首先,Java规范中没有强制规定boolean所占内存的大小。而且大部分计算机允许分配的最小内存单元为8bit

    四、可以用运用BitMap解决问题的实用场景

    大多可以运用的场景主要是两个方面:
    这里以标签匹配为例子,开发中一个用户与各个用户之间的标签匹配度是令人头疼的问题,通过匹配标签字符串或者标签ID,这样的效果都不能太让人满意,在数据库中的保存也颇为麻烦。

    一、快速索引

    假如,每个用户都有一个这样小小的长度为40的byte数组,那么用户就可以用它来表示320种标签。而且能够快速的查询,通过bitarray[tag_id]这样的访问方式可以极快查到,用户是否选取了这个标签,能够快速地计算与各个用户之间的标签匹配度

    二、数据压缩

    那么像第一点说的那样,长度为40的byte数据便可以保存320种标签信息,但它内存大小只有40B。而且这还是没有进行游程编码压缩之前的大小

    五、Java实现

    
    /**
    * Created by auhnayuil on 17-6-7.
    */
    public class BitMap {

    public static final int DEFAULT_SIZE = 1024;

    public static final boolean EXIST = true;

    public static final boolean NULL = false;

    public static final short bits = 8;

    private byte[] bitArray;

    private int size;

    public BitMap(){
    this(DEFAULT_SIZE);
    }

    public BitMap(byte[] bitArray){
    this.size = bitArray.length * bits;
    this.bitArray = bitArray;
    }

    public BitMap(int defaultSize) {
    this.size = defaultSize * bits;
    this.bitArray = new byte[defaultSize];
    }

    public BitMap(int size, boolean elem){
    this(size);

    if(EXIST == elem) {
    for (int i = 0; i < bitArray.length; i++)
    bitArray[i] = (byte) ~bitArray[i];
    }
    }

    public int size(){
    return size;
    }

    public int index(int position){
    int idx = (position + bits - 1) / bits;
    return idx - 1;
    }

    public int offset(int position){
    int ofs = position % 8;
    return (ofs == 0 ? ofs : 8 - ofs);
    }

    public void setBit(int position){
    if(position > size)
    return ;

    int idx = index(position);
    int ofs = offset(position);
    bitArray[idx] |= (byte)(1 << ofs);
    }

    public boolean getBit(int position){
    if(position > size)
    return false;

    int idx = index(position);
    int ofs = offset(position);
    byte tmp = (byte)(bitArray[idx] & (1 << ofs));

    return tmp != 0;
    }

    public void setBitArray(byte[] bitArray){
    this.bitArray = bitArray;
    }

    public byte[] getBitArray(){
    return bitArray;
    }

    public String byteToStr(int position){
    byte b = bitArray[index(position)];

    StringBuffer sb = new StringBuffer("");
    for(int i=bits-1; i>-1; i--)
    sb.append((byte)((b >> i) & 0x1));
    return sb.toString();
    }
    }

  • 相关阅读:
    Spring MVC Ajax 嵌套表单数据的提交
    Spring MVC 过滤静态资源访问
    Spring MVC 页面跳转时传递参数
    IDEA Maven 三层架构 2、运行 springMVC
    IDEA Maven 三层架构 1、基本的Archetype 搭建
    EasyUI DataGrid 基于 Ajax 自定义取值(loadData)
    Spring MVC Ajax 复杂参数的批量传递
    Mybatis Sql片段的应用
    在 Tomcat 8 部署多端口项目
    自动升级的设计思路与实现
  • 原文地址:https://www.cnblogs.com/chenjunping/p/6968409.html
Copyright © 2011-2022 走看看