Redis网站热搜关键词加载实践,建议收藏
俠夢的開發筆記回復【面試題】獲取2021年最新java面試題合集~
來源:Catcher8
www.cnblogs.com/catcher1994/p/5877262.html
對于一個網站來說,無論是商城網站還是門戶網站,搜索框都是有一個比較重要的地位,它的存在可以說是為了讓用戶更快、更方便的去找到自己想要的東西。對于經常逛這個網站的用戶,當然也會想知道在這里比較“火”的東西是什么,這個時候我們搜索框上的熱詞就起作用了。其實我覺得這一塊的完善會對這個網站帶來許多益處。
可能現在比較普遍的做法是把這些相應的信息存到我們的關系型數據庫中,如sql server 和 oracle。方便起見的話,可能每搜索一次就往表里插一次數據,用的時候要先統計數據,統計完后再排序,最后才展示。這種情況下,如果搜索量很大的話,表的膨脹速度就會非常快,如果sql沒寫好,查詢的時候估計會。。相比Redis,同等條件下,Redis的速率肯定是會較優,畢竟是從內存中拿出來的。
?
下面我們就用.NET Core和StackExchange.Redis來做一下這個簡單的案例。
案例用到的一些相關技術和說明:
| 技術 | 說明? |
| .NET Core | 網站嘛,你懂的。有事沒事用Core寫寫Demo,免得跟不上發展的腳步。 |
| Redis | 存儲搜索詞,用了主從的模式,主寫從讀 |
| Jquery-ui | 主要是用了里面的autocomplete |
開始正題之前,我們要確定用Redis中的那種數據結構,五種之中比較合適的應該是SortedSet,我們可以用成員來作為搜索詞,成員分數來作為搜索詞的搜索次數,這樣就可以很方便的來操作相關的數據了。
下面開始正題:
我們在開始的時候需要初始化一下數據。這里就直接在第一次運行的時候初始化。用上流水線的技術,速度還是很可觀的。初始化了70個搜索關鍵詞(NBA球星),然后用隨機數作為關鍵字的下標,去隨機給這個關鍵字加1分。這個分數就是這個關鍵字被搜索的次數。下面來看看初始化的相關代碼:
public?IActionResult?Index(){//keysIList<string>?keys?=?new?List<string>(){"kobe","johnson","jabbar","west","o'neal","baylor","mccann","worthy","gasol","chamberlain","fisher","odom","bynum","horry","rambis","riley","clarkson","Williams","young","Russell","ingram","randle","nance","brown","deng","yi","ariza","artest","walton","vujacic","james","paul","curry","park","yao","kevin","wade","rose","popovich","leonard","aldridge","ginobili","duncan","lavine","rubio","garnett","wiggins","westbrook","durant","ibaka","nowitzki","pierce","crawford","love","smith","iguodala","barnes","green","thompson","harden","lillard","mccollum","lin","jackson","nash","stoudemire","whiteside","dragic","Howard","batum"};//initRandom?random?=?new?Random();var?tran?=?_redis.GetTransaction();for?(int?i?=?0;?i?<?1000000;?i++){tran.SortedSetIncrementAsync(_searchKey,?keys[random.Next(0,?70)],?1);}tran.ExecuteAsync();return?View();}這里是在加載這個頁面的時候就把這些熱搜詞存進Redis中,這樣我們才能有數據來演示啊。這里還用到了一個非事務型的流水線。就是把要操作的指令存放到一個隊列中,最后把這個隊列扔到服務端去執行,這樣就有效的減少了不必要的網絡傳輸,同時也提高了執行速度。
好了,初始數據有了,下面要做的就是用戶在搜索的時候,根據用戶的輸入去匹配搜索次數多的關鍵字,展示最Hot的10個,當然這個展示的個數是隨我們定的,最后可以考慮把這個放到我們的配置文件中去,甚至是放到數據庫中,
為的是靈活和方便維護。下面是我們在后臺的處理邏輯:
public?IActionResult?GetHotKey(string?key=""){if?(string.IsNullOrEmpty(key)){//defaultvar?res?=?_redis.ZRevRange(_searchKey,?0,?9);var?list?=?(from?i?in?res?select?i.ToString());return?Json(list);}else{//by?user?inputvar?res?=?_redis.ZRevRange(_searchKey,?0,?-1);var?list?=?(from?i?in?res?select?i.ToString()).Where(x?=>?x.Contains(key)).Take(10).ToList();return?Json(list);}}對于查詢的處理是非常的簡單的,用戶不小心輸入空格的時候就展示最熱的10個關鍵詞,如果用戶有輸入的話,就把關鍵詞中包含用戶輸入的展示出來。那么我們在頁面上要做些什么呢?下面就是我們演示用的搜索框。
<div?class="row"><div?class="col-md-6?col-md-offset-4"?style="padding-top:50px;"><input?id="key"?name="key"?placeholder="search"?class="form-control?col-md-4"><button?class="btn?btn-primary"?type="button"?id="searchSubmit">Search</button><div?id="result"></div></div> </div>相應的js是寫到 scripts 這個p中的,js的話是比較簡單的就是用ajax去請求我們要展示的數據。更多的應該是jquery-ui的api問題,大家也可以換用自己比較熟悉的組件,舉一反三即可。下面是autocomplete的api??,如果有需要可以去看一下。
@p?scripts{<script?type="text/javascript">$(function?()?{//show?hot?keyword$("#key").autocomplete({????????????????source:?function?(request,?response)?{$.ajax({url:?"@Url.Action("GetHotKey",?"Auto")",dataType:?"json",data:?{key:?request.term},success:?function?(data)?{response(data);}});},});????????????</script> }到這里,用戶搜索前的操作,我們是做好了,下面先來看一下效果。
那么用戶點擊了搜索之后我們要做些什么處理呢?無論是新的關鍵字還是已有的關鍵字,我們都是要做處理的,當然redis中zincrby命令來處理這個是十分合適的,存在的就把分數加1,不存在就創建一個分數為1的成員。下面是搜索時的后臺邏輯處理:
[HttpPost]public?IActionResult?SetHotKey(string?key){if?(!string.IsNullOrWhiteSpace(key)){_redis.ZIncrby(_searchKey,key);//other?//...return?Json(new?{?code?=?"000",?msg?=?"OK"?});}else{return?Json(new?{?code?=?"999",?msg?=?"keyword?can?not?be?empty!"?});}}限制了用戶不能搜索空關鍵字,在把這個關鍵字存儲或者分數加一之后,就是展示我們的搜索的結果。這個搜索的結果一般是從solr等全文檢索的地方查出來的,不是我們講的重點,所以就忽略了。然后我們還要加一段js去處理我們搜索的時候應該做的操作。當然,都是些比較簡單的操作。
//search$("#searchSubmit").click(function?()?{$.ajax({url:?"@Url.Action("SetHotKey",?"Auto")",dataType:?"json",type:?"POST",data:?{?key:?$("#key").val()?},success:?function?(data)?{if?(data.code?==?"000")?{$("<p>search?successful!</p>").appendTo("#result");}?else?{$("<p>"+data.msg+"</p>").appendTo("#result");}}});});下面是效果圖:
在演示的時候,我們搜索了“我愛你”和“我不信”,在Redis的客戶端我們找出搜索次數最少的6個,然后就可以看到我們那兩個關鍵字最的分數都是1。確定是剛插入的數據。
到這里,我們做的這個熱搜詞可以說是大功告成了。當然這可以說是最最最簡單的一個雛形。我們還可以適當的添加一些東西讓這個功能變得更加完善。比如我可以在搜索展示的時候顯示一下搜索的次數等。
最后是完整的控制器和頁面代碼:
using?AutoCompleteDemo.Common; using?Microsoft.AspNetCore.Mvc; using?System; using?System.Collections.Generic; using?System.Linq;namespace?AutoCompleteDemo.Controllers {public?class?AutoController?:?Controller{private?readonly?IRedis?_redis;private?readonly?string?_searchKey?=?"search";????????public?AutoController(IRedis?redis){_redis?=?redis;}public?IActionResult?Index(){//keysIList<string>?keys?=?new?List<string>(){"kobe","johnson","jabbar","west","o'neal","baylor","mccann","worthy","gasol","chamberlain","fisher","odom","bynum","horry","rambis","riley","clarkson","Williams","young","Russell","ingram","randle","nance","brown","deng","yi","ariza","artest","walton","vujacic","james","paul","curry","park","yao","kevin","wade","rose","popovich","leonard","aldridge","ginobili","duncan","lavine","rubio","garnett","wiggins","westbrook","durant","ibaka","nowitzki","pierce","crawford","love","smith","iguodala","barnes","green","thompson","harden","lillard","mccollum","lin","jackson","nash","stoudemire","whiteside","dragic","Howard","batum"};//initRandom?random?=?new?Random();var?tran?=?_redis.GetTransaction();for?(int?i?=?0;?i?<?2000000;?i++){tran.SortedSetIncrementAsync(_searchKey,?keys[random.Next(0,?70)],?1);}tran.ExecuteAsync();return?View();}public?IActionResult?GetHotKey(string?key=""){if?(string.IsNullOrEmpty(key)){//defaultvar?res?=?_redis.ZRevRange(_searchKey,?0,?9);var?list?=?(from?i?in?res?select?i.ToString());return?Json(list);}else{//by?user?inputvar?res?=?_redis.ZRevRange(_searchKey,?0,?-1);var?list?=?(from?i?in?res?select?i.ToString()).Where(x?=>?x.Contains(key)).Take(10).ToList();return?Json(list);}}[HttpPost]public?IActionResult?SetHotKey(string?key){if?(!string.IsNullOrWhiteSpace(key)){_redis.ZIncrby(_searchKey,key);//other?//...return?Json(new?{?code?=?"000",?msg?=?"OK"?});}else{return?Json(new?{?code?=?"999",?msg?=?"keyword?can?not?be?empty!"?});}}} }AutoController @{ViewData["Title"]?=?"Auto?Complete"; } <div?class="row"><div?class="col-md-6?col-md-offset-4"?style="padding-top:50px;"><input?id="key"?name="key"?placeholder="search"?class="form-control?col-md-4"><button?class="btn?btn-primary"?type="button"?id="searchSubmit">Search</button><div?id="result"></div></div> </div> @p?scripts{<script?type="text/javascript">$(function?()?{//show?hot?keyword$("#key").autocomplete({????????????????source:?function?(request,?response)?{????????????????????$.ajax({url:?"@Url.Action("GetHotKey",?"Auto")",dataType:?"json",data:?{key:?request.term},success:?function?(data)?{response(data);}});},});//search$("#searchSubmit").click(function?()?{$.ajax({url:?"@Url.Action("SetHotKey",?"Auto")",dataType:?"json",type:?"POST",data:?{?key:?$("#key").val()?},success:?function?(data)?{if?(data.code?==?"000")?{$("<p>search?successful!</p>").appendTo("#result");}?else?{$("<p>"+data.msg+"</p>").appendTo("#result");}}});});});</script> }Index.cshtml--完--
回復【干貨】獲取精選干貨視頻教程
回復【加群】加入疑難問題攻堅交流群
回復【mat】獲取內存溢出問題分析詳細文檔教程
回復【賺錢】獲取用java寫一個能賺錢的微信機器人
回復【副業】獲取程序員副業攻略一份
戳這兒
總結
以上是生活随笔為你收集整理的Redis网站热搜关键词加载实践,建议收藏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++学习(三)LHS RHS
- 下一篇: 长尾序列用户行为建模中可转移参数的学习(