1. 程式人生 > >基於redis 實現布隆過濾器

基於redis 實現布隆過濾器

簡介

Redis中有一個數據結構叫做Bitmap(下方有官網詳解),它提供一個最大長度為512MB(2^32)的位陣列。我們可以把它提供給布隆過濾器做位陣列。

根據《數學之美》中給出的資料,在使用8個雜湊函式的情況下,512MB大小的位陣列在誤報率萬分之五的情況下可以對約兩億的url去重。而若單純的使用set()去重的話,以一個url64個位元組記,兩億url約需要128GB的記憶體空間,不敢想象。

我使用的策略是使用雜湊函式算出的雜湊值對2^32取模,填入bitmap中。
 

本文主要是介紹這種思想和用法,具體業務使用過程中,需要具體實現,下面貼出程式碼 演示最簡單的一種使用方法:

/*
	 * 模擬專案啟動時候 從"資料庫"或者其他地方獲取到的過濾器集合的資料
	 */
	static List<String> l = new ArrayList<String>();

	// 模擬生成的訂單號/使用者/商品ID
	static {
		l.add("201810120001");
		l.add("201810120002");
		l.add("201810120003");
		l.add("201810120004");
	}

	/**
	 * 單機版測試
	 */
	@Test
	public void TestRedis() {
		Jedis jedis = new Jedis("192.168.1.118", 6379);

		// 獲取redis支援的最大長度作為取模的基數
		double size = Math.pow(2, 32);
		// 迴圈l 取出裡面的資料,放入到redis中
		l.forEach(orderId -> {
			long index = Math.abs((long) (orderId.hashCode() % size));
			jedis.setbit("orderId", index, true);
		});
		
		

		// 判斷指定值是否在過濾器裡面
		String orderId = l.get(0);
		//String orderId = "201810120005";
		long index =  Math.abs((long) (orderId.hashCode() % size));
		boolean contain = jedis.getbit("orderId", index);
		// 為true 說明在裡面
		if (contain) {
			System.out.println("包含這個值.");
			// 否則不在
		} else {
			System.out.println("不包含這個值.");
		}


		jedis.close();
	}

執行結果 orderId如果在l集合裡面 就顯示包含,否則就不包含