日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

redis缓存原理与实现_基于Redis实现范围查询的IP库缓存设计方案

發布時間:2024/7/23 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis缓存原理与实现_基于Redis实现范围查询的IP库缓存设计方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
點擊上方“碼農沉思錄”? 發現更多精彩我先說下結果。我現在還不敢放線上去測,這是本地測的數據,我4g內存的電腦本地開redis,一次都沒寫完過全部數據,都是寫一半后不是redis掛就是測試程序掛。可以肯定的是總記錄數是以千萬為單位的。O(log(n千萬/range))的時間復雜度,本地測的結果我并不滿意,7ms的時間,太久了。這個數量級的數據,就算內存緩存也很花時間,因為并不是簡單的key-value,涉及到范圍查找。使用Sorted Set實現范圍查找最近系統需要更新IP庫,IP庫存儲的是IP所屬的國家和城市信息,廣告主投放廣告會有區域限制,所以需要根據點擊廣告的終端ip,獲取位置信息,并判斷是否滿足廣告投放區域的要求。最頭疼的是,IP信息庫是按區間存儲的,拿到一個ip得要知道它所屬的范圍才能知道它對應哪條記錄。它的表結構是這樣的:Ip_from,ip_to,ccountry_code,country,regin,cityIp起始段,Ip結束段,國家編碼,國家,區域(比如中國的省),城市而Ip_from和ip_to是一個數值,將ip通過公式轉化后的數值。a.b.c.dA*(256*256*256)+b*(256*256)+c*(256)+d為了效率,程序中的轉換可以寫為a*(1<<24)+b*(1<<16)+c*(1<<8)+d在此之前我都沒注意以前是怎么實現查找的,以前是用內存緩存實現,但以前的數據比較少,而查找的方式用的遞歸,先不說遞歸查找算法的缺陷。而新的ip庫數據量很大,本地debug直接OOM,沒有足夠的內存撐起這么大的ip庫。如果說,一個csv文件的大小是1g多,那么讀取到jvm中,就需要4g甚至更高的內存,因為一個對象占的內存是比一行逗號隔開的字符串耗更大的內存。要實現查找算法,創建對應的數據結構,這些也會占用很大的內存。綜上所述,我們考慮用redis來緩存,當然,也可以用mongodb,如果是用mongodb緩存,那就簡單了。既然要用Redis,那么就不得不面對,Redis如何實現范圍查詢,還要支持高并發。這算是一道難題了。插入一段內容,關于如果使用Sorted Set實現范圍查找,就是sql中的大于等于and小于等于。(下面是我參考的一篇博客,我覺得他的實現有些雞肋,完全可以用一條:zadd myset 1015 1011-1015-v1 替代兩條記錄)。服務端對于客戶端不同的版本區間會做些不同的配置,那么客戶端一個版本過來怎么快速的定位是屬于哪個版本區間呢?可以利用Sorted Sets的zrangebyscore命令。zadd myset 1011 v1_startzadd myset 1015 v1_end?zadd myset 1018 v2_start?zadd myset 1023 v2_end?如上我們像myset里插入了4條數據,代表的意思是版本區間v1是從1011-1015版本,版本區間v2是從1018-1023版本。https://www.cnblogs.com/zhanjindong/p/3549994.html那么我現在如何判斷1014版本屬于哪個區間呢,使用zrangebyscore如下操作:?zrangebyscore myset 1014 +inf LIMIT 0 1?1)v1_end?返回v1_end說明1014屬于版本區間1,上面的這個命令的意思是在myset中查找第一個score值大于等于1014的member,如果我們查找一個不在區間內的版本,比如1016:?zrangebyscore myset 1014 +inf LIMIT 0 1?1)v2_starthttps://www.cnblogs.com/zhanjindong/p/3549994.html首先,我想到的是利用Redis的有序集合Sorted Set,存儲每條記錄的ip區間,或者叫ip范圍。ip_to列作為有序集合的score。如:zadd?ip-country-city-locations-range?3756871679?3756871424~3756871679這樣就可以查詢一個ip對應的score落在哪個區間,找出符合條件的第一個區間。如:(1)將ip轉為number,假設得到的值為:3756871650(2)使用zrangebyscore命令獲取所在區間zrangebyscore?ip-country-city-locations-range?3756871650?+inf?0 1因為3756871650比3756871424~3756871679區間的end值3756871679小于等于,所以匹配到這條記錄。但拿到這條記錄后并不能說明3756871650在這個區間內,所以還要比較3756871424<=3756871650<=3756871679因為會存在這種情況,該區間與前一個區間并不是連續的,比如。(1)3756870911=>3756870656~3756870911(2)3756871679=>3756871424~3756871679明顯,這兩個區間之間存在斷層。但可以肯定的是,如果不落在區間(2)中,也不會落在區間(1)。所以不滿足就可以直接返回null了。// [0] <= midNumber <= [1]if?(midNumber.compareTo(Long.valueOf(rangeSn[0]))????||?midNumber.compareTo(Long.valueOf(rangeSn[1]))?>?0)?{ return null;}Ip庫用hash類型存儲,field取ip_from或者ip_from&ip_to,value當然就是存完整的一行記錄了。最后就可以根據拿到的區間信息獲取到對應記錄的field,使用hget命令就能獲取到最終的一行ip信息記錄。hget ip-country-city-locations 3756871424這并不難實現,但是,耗時卻非常嚴重,可以看下官方文檔介紹的Sorted Set的zrangebyscore的時間復雜度。IP庫保守估計百萬條記錄,如果就這樣上線,百分百又是服務雪崩。改進思路:區間+Sorted Set由于Sorted Set有序集合的查詢時間復雜度是O(log(n)+m),其中n是總記錄數,m是此次查詢獲取的記錄數,在limit 0 1的情況下是O(log(n)),所以一個有序集合的元素個數越多,它的查詢時間耗時越長。對于一般的應用場景,如排行榜,都是只有極少數的幾百條記錄。而如果用于ip庫的區間查詢實現,記錄上百萬條,而且還是用于高并發場景,不把服務搞垮才怪了。既然我們要用Sorted Set,但又不能讓集合的元素過大,那么我們可以分n/m個區間存儲啊。假設有一百萬條記錄,每個Sorted Set存儲1000條,那就用1000個Sorted Set集合來存儲。hash的查詢時間復雜度是接近O(1)的,增加1000個key在分槽位的分布式集群下根本不算什么。按照上面的思路改進后,獲取一個ip的國家城市信息就變成如下步驟:1、根據ip計算出一個number值比如:37568716502、根據區間大小(這一步的區間指的是每個Sorted Set的最大大小),計算出該number所在的集合的key比如:ip-country-city-locations-range-3753、根據這個key,去Sorted Set查詢number所屬的區間。比如:zrangebyscore ip-country-city-locations-range 3756871650 +inf 0 15、拿到區間信息后,從區間信息獲取ip范圍位置信息的 field(hash類型存儲)比如查詢結果區間信息為:3756871424~3756871679拿到field就是:37568714246、根據key和field拿到目標記錄。hget ip-country-city-locations 3756871424編碼實現我將實現封裝成一個組件,目的是對外提供更簡單的使用方式,封裝復雜的實現邏輯,同時,內部的改動對使用者無感知。通過SPI+分層設計,利用靜態代理模式等,使得組件具有極強的擴展性,如果某天想改成使用mongodb或者內存緩存,只需要實現幾個接口就可以了。下面是README.MD的內容

關于數據源表的初始化

使用需要配置update啟動參數:

-Dip.database.table.update=true

如:

java -Xss256k-jar -Dip.database.table.update=true xxx-1.0.0.jar

true: 首次啟動就會從指定的url文件讀取解析記錄,插入數據表 false: 表示已經確認表存在記錄了,不需要再更新。(也不會去解析文件) 默認:false解析記錄與插入表是異步的,后臺開啟一個線程執行。耗時根據文件大小決定,我測的是86s

配置使用表

使用了java的SPI需要指定使用哪個文件解析器,也就對應使用哪種類型的表

配置redis操作實現類

使用了java的SPI如果解析配置使用了

com.chestnut.ip.database.parser.RedisIP2LocationFileParser

則需要自己實現RedisOperation,并在

com.chestnut.ip.database.suppor.IP2LocationRedisOperation

文件中配置redis操作的實現類

緩存的key

如果使用redis存儲數據,則key固定為

ip-country-city-locations // 存儲真實記錄

ip-country-city-locations-range-* // 存儲范圍與真實記錄的key的映射

其中ip-country-city-locations-range-后面的代表的分區索引點個在看吧,證明你還愛我

總結

以上是生活随笔為你收集整理的redis缓存原理与实现_基于Redis实现范围查询的IP库缓存设计方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 98av视频| 一区二区三区在线视频免费观看 | 午夜成人影片 | 日产国产亚洲精品系列 | 黄色欧美大片 | 亚洲精品永久免费 | 奇米影视777四色 | 91中文字幕网| 国产性生活网站 | 一区二区三区免费播放 | 日本中文字幕观看 | 红桃视频网站 | 欧美做爰xxxⅹ性欧美大片 | 国产一级自拍 | av免费资源 | 亚洲一级特黄毛片 | 久草热在线观看 | 性欧美久久 | 欧美视频色 | 91精品国产综合久久久久久 | 少妇人妻互换不带套 | 婷婷激情图片 | 久久久久久福利 | 国产精品视频在线免费观看 | 国产成人综合网 | 精品视频一区二区 | 久久免费少妇高潮久久精品99 | av免费播放网站 | 爽爽爽av | 美味的客房沙龙服务 | 嫩草视频在线看 | 成人午夜精品一区二区三区 | 4hu最新网址 | 日韩欧美中文在线观看 | 殴美一级片 | 一区二区三区不卡在线 | 91福利一区 | 亚洲精品黄色片 | 免费午夜人成电影 | 日韩一级色 | 黄色二级毛片 | 亚洲一区视频 | 99久久毛片| 成人免费毛片男人用品 | 久久成人国产精品入口 | 国产精品1区2区3区4区 | 国产午夜免费视频 | 九九免费| 国产成人亚洲精品 | 1024你懂的日韩 | v片在线看 | 女人被男人躁得好爽免费视频 | 中文字幕一区二区人妻痴汉电车 | 亚洲欧美日本在线观看 | 美女网站全黄 | 久久人妻免费视频 | 国产乱xxⅹxx国语对白 | 91成人精品一区在线播放 | 国产在视频线精品视频 | 国产女人18水真多毛片18精品 | 免费观看成人鲁鲁鲁鲁鲁视频 | 黄色理伦 | 艳妇臀荡乳欲伦交换h漫 | 亚洲成人无码久久 | 69视频免费看 | 欧美丰满美乳xxⅹ高潮www | 操综合 | 免费又黄又爽又色的视频 | 一区二区三区福利 | 91国产网站 | 无码久久av一区二区三区 | 一色道久久88加勒比一 | 午夜伦理影院 | 日本大胆人体视频 | free性护士vidos猛交 | 国产黄色大片 | 成人黄色a| 亚洲经典自拍 | 内地级a艳片高清免费播放 91在线精品一区二区 | 黄色不卡视频 | 日韩mv欧美mv国产网站 | 亚洲青春草 | 丰满的人妻hd高清日本 | 亚洲日本色图 | 在线观看 一区 | 成人中文字幕在线观看 | 中国黄色一级片 | 伊人影院综合 | 蜜桃视频在线观看www | 国产黄色在线网站 | 69影院少妇在线观看 | 男人天堂aaa | 久久香蕉网 | 激情超碰在线 | 欧美在线a | 日韩一区二区三区不卡视频 | 日韩精品一区二区在线播放 | 亚洲爱v| 99re这里只有精品首页 |