在流量高峰期,會有大量的請求去查詢一個快取和資料庫中都沒有的資料,這時所有的請求就會到達資料庫裡去;當源源不斷地發起請求時,就會打垮資料庫。
這裡我們有一種解決方案就是使用布隆過濾器。下面是布隆過濾器的一個簡單介紹:
布隆過濾器(Bloom Filter)是1970年由布隆提出的。布隆過濾器是一種資料結構,利用極小的記憶體,可以判斷大量的資料。它告訴我們:“如果資料不存在,就肯定不存在”。
布隆過濾器原理
例如:
對“oracle”分別進行三次的hash函式計算,得到3個數值:1、4、5,於是就在對應的陣列的位置上標誌上1。
本文重在實踐,主要是解決布隆過濾器的程式碼實現。要詳細瞭解布隆過濾器的可以自行百度。
布隆過濾器的實現一般有兩種,一種是用谷歌公司提供的guava 工具包;一種是透過Redis底層的資料結構 bitmap 來實現布隆過濾器,客戶端工具Redisson已經封裝好對應的功能。
下面介紹這2種方式:
2、程式碼實現,具體的解釋看註釋好了import com.google.common.hash.BloomFilter;import com.google.common.hash.Funnels;public class GuavaBloomFilter { public static void main(String[] args) { //後邊兩個引數:預計包含的資料量,和允許的誤差值 BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), 100000, 0.01); for (int i = 0; i < 100000; i++) { bloomFilter.put(i); } System.out.println(bloomFilter.mightContain(1)); System.out.println(bloomFilter.mightContain(2)); System.out.println(bloomFilter.mightContain(3)); System.out.println(bloomFilter.mightContain(100001)); }}
3、執行結果truetruetruefalse
和實驗相符。
二、客戶端工具Redisson方式Redisson實現的方式其實是用了redis來實現的。
1、redis安裝關於redis的安裝
(1)可以用docker快速安裝單個例項
sudo docker run -p 36379:6379 --name redis5.0 -d redis:5.0 redis-server --appendonly yes
也可以用上次我說到的哨兵模式。
(2)在上篇中已向大家介紹了redis的哨兵方式及使用的方案。如需要看的可以跳轉到下面:
https://www.toutiao.com/i6913744392666841604/
2、程式碼實現:
在程式碼裡已經包括這2種方式,看原始碼即可。
(1)加入jar包 <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.5</version> </dependency>
(2)實現方式A、如果需要用單redis例項方式:
config.useSingleServer().setAddress("redis://192.168.197.24:36379");
B、如果用哨兵模式:
//指定使用哨兵部署方式 config.useSentinelServers() //設定sentinel.conf配置裡的sentinel別名 //比如sentinel.conf裡配置為sentinel monitor mymaster 192.168.197.24 6379 2,那麼這裡就配置mymaster .setMasterName("mymaster") //這裡設定sentinel節點的服務IP和埠,sentinel是採用Paxos拜占庭協議,一般sentinel至少3個節點 //記住這裡不是配置redis節點的服務埠和IP,sentinel會自己把請求轉發給後面monitor的redis節點 .addSentinelAddress("redis://192.168.197.24:26379") .addSentinelAddress("redis://192.168.197.24:26380") .addSentinelAddress("redis://192.168.197.24:26381");
可看全部的程式碼如下:
import org.redisson.Redisson;import org.redisson.api.RBloomFilter;import org.redisson.api.RedissonClient;import org.redisson.config.Config;public class RedissonBloomFilter { public static void main(String[] args) { Config config = new Config(); //單redis例項方式// config.useSingleServer().setAddress("redis://192.168.197.24:36379"); //指定使用哨兵部署方式 config.useSentinelServers() //設定sentinel.conf配置裡的sentinel別名 //比如sentinel.conf裡配置為sentinel monitor mymaster 192.168.197.24 6379 2,那麼這裡就配置mymaster .setMasterName("mymaster") //這裡設定sentinel節點的服務IP和埠,sentinel是採用Paxos拜占庭協議,一般sentinel至少3個節點 //記住這裡不是配置redis節點的服務埠和IP,sentinel會自己把請求轉發給後面monitor的redis節點 .addSentinelAddress("redis://192.168.197.24:26379") .addSentinelAddress("redis://192.168.197.24:26380") .addSentinelAddress("redis://192.168.197.24:26381"); RedissonClient redisson = Redisson.create(config); RBloomFilter<String> bloomFilter = redisson.getBloomFilter("user"); // 初始化布隆過濾器,預計統計元素數量為55000000,期望誤差率為0.03 bloomFilter.tryInit(55000000L, 0.03); bloomFilter.add("yaokj"); bloomFilter.add("jamaly"); System.out.println(bloomFilter.count()); //2 System.out.println(bloomFilter.contains("yaokj")); //true System.out.println(bloomFilter.contains("xiaokua")); //false //最後關閉RedissonClient redisson.shutdown(); }}
(3)執行結果三、原始碼原始碼已開放,可以看連結:
https://gitee.com/yaokj/demo-toutiao
最新評論