javascript
微服务Spring Boot 整合 Redis 实现好友关注 – Feed流实现推送到粉丝收件箱
文章目錄
- ?引言
- 一、Redis 實現好友關注 -- Feed流實現推送到粉絲收件箱
- ?Feed 流實現方案
- ?推送到粉絲收件箱
- 三、Redis 實現好友關注 -- 實現分頁滾動查詢 實時獲取信息
- ?小結
?引言
本博文參考 黑馬 程序員B站 Redis課程系列
在點評項目中,有這樣的需求,如何 Redis 實現好友關注 – Feed流實現推送到粉絲收件箱 功能?
采用 Feed流實現推送到粉絲收件箱
Redis 如此強大!
一、Redis 實現好友關注 – Feed流實現推送到粉絲收件箱
?Feed 流實現方案
假設我們關注了用戶,這個用戶發布了動態,那么就應該把當前用戶發布的動態推送給他的粉絲,如何實現呢,這個我們把它叫做Feed流,關注推送也叫做 Feed流 ,直譯為投喂,為用戶持續的提供 ”沉浸式“ 的體驗,通過五險下拉刷新獲取新的信息。
傳統模式是我們需要用戶去通過搜索引擎或者是其它的方式去解鎖想要看的內容
新型的Feed流: 不需要用戶再去推送消息,而是系統分析用戶到底想要什么,然后直接把內容推送給用戶,從而使用戶能夠更加的節約時間,不用主動尋找。
Feed流主要分為兩種實現方式:
TimeLine: 不做內容篩選,簡單的按照內容發布時間排序,常用于好友或關注。例如朋友圈
- 優點:信息全面,不會有缺失。并且實現也相對簡單
- 缺點:信息噪音較多,用戶不一定感興趣,內容獲取效率低
智能排序:利用智能算法屏蔽掉違規的、用戶不感興趣的內容。推送用戶感興趣信息來吸引用戶
- 優點:投喂用戶感興趣信息,用戶粘度很高,容易沉迷
- 缺點:如果算法不精準,可能起到反作用
本次實現的功能中,是基于好友 來做Feed流,因此采用 TimeLine 模式。 該模式的實現方案分為三種
- 拉模式
- 推模式
- 推拉結合
拉模式:也叫做讀擴散
該模式的核心含義就是:當張三和李四和王五發了消息后,都會保存在自己的郵箱中,假設趙六要讀取信息,那么他會從讀取他自己的收件箱,此時系統會從他關注的人群中,把他關注人的信息全部都進行拉取,然后在進行排序
優點:比較節省空間,因為用戶在讀取信息時,并沒有重復讀取,而是讀取完后可以把他的收件箱進行清除
缺點:比較延遲,當用戶讀取數據時才去關注的用戶的人里面讀取數據,假設用戶關注了大量的用戶,那么此時就會拉取海量的數據內容,對服務器壓力比較大。
推模式:也叫做寫擴散
推模式是沒有寫郵箱的,當張三寫了一個內容,此時會主動的把張三寫的內容發送到他的粉絲收件箱中去,假設此時李四再來讀取,就不用再去臨時拉取了
優點:時效快,不用臨時拉取
缺點:內存壓力大,假設一個大V寫信息,很多人關注他,就會寫很多的數據到粉絲收件箱,加大服務器壓力。
推拉結合模式:也叫做讀寫混合,兼具推和拉兩種模式的優點
推拉模式是一個折中的方案,站在發件人這一段,如果是個普通的人,那么我們采用寫擴散的方式,直接把數據寫入到他的粉絲中去,因為普通的人他的粉絲關注量比較小,所以這樣做沒有壓力,如果是大V,那么他是直接將數據先寫入到一份到發件箱里邊去,然后再直接寫一份到活躍粉絲收件箱里邊去,現在站在收件人這端來看,如果是活躍粉絲,那么大V和普通的人發的都會直接寫入到自己收件箱里邊來,而如果是普通的粉絲,由于他們上線不是很頻繁,所以等他們上線時,再從發件箱里邊去拉信息。
?推送到粉絲收件箱
需求:
- 修改新增探店筆記的業務,在保存blog到數據庫的同時,推送到粉絲的收件箱
- 收件箱滿足可以根據時間戳排序,必須用Redis的數據結構實現
核心:當我們保存完筆記后,獲取當前用戶的粉絲,然后把數據推送到粉絲的Redis中。
@Override public Result saveBlog(Blog blog) {// 1.獲取登錄用戶UserDTO user = UserHolder.getUser();blog.setUserId(user.getId());// 2.保存探店筆記boolean isSuccess = save(blog);if(!isSuccess){return Result.fail("新增筆記失敗!");}// 3.查詢筆記作者的所有粉絲 select * from tb_follow where follow_user_id = ?List<Follow> follows = followService.query().eq("follow_user_id", user.getId()).list();// 4.推送筆記id給所有粉絲for (Follow follow : follows) {// 4.1.獲取粉絲idLong userId = follow.getUserId();// 4.2.推送String key = FEED_KEY + userId;stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());}// 5.返回idreturn Result.ok(blog.getId()); }進行測試
發布筆記
查看粉絲收件箱
三、Redis 實現好友關注 – 實現分頁滾動查詢 實時獲取信息
滾動分頁查詢思路分析
Feed流中的數據會不斷更新,所以數據的角標也在變化,因此不能采用傳統的分頁模式。
傳統了分頁在feed流是不適用的,因為我們的數據會隨時發生變化
假設在t1 時刻,我們去讀取第一頁,此時page = 1 ,size = 5 ,那么我們拿到的就是10~6 這幾條記錄,假設現在t2時候又發布了一條記錄,此時t3 時刻,我們來讀取第二頁,讀取第二頁傳入的參數是page=2 ,size=5 ,那么此時讀取到的第二頁實際上是從6 開始,然后是6~2 ,那么我們就讀取到了重復的數據,所以feed流的分頁,不能采用原始方案來做。
Feed流的滾動分頁
我們需要記錄每次操作的最后一條,然后從這個位置開始去讀取數據
舉個例子:我們從t1時刻開始,拿第一頁數據,拿到了10~6,然后記錄下當前最后一次拿取的記錄,就是6,t2時刻發布了新的記錄,此時這個11放到最頂上,但是不會影響我們之前記錄的6,此時t3時刻來拿第二頁,第二頁這個時候拿數據,還是從6后一點的5去拿,就拿到了5-1的記錄。我們這個地方可以采用sortedSet來做,可以進行范圍查詢,并且還可以記錄當前獲取數據時間戳最小值,就可以實現滾動分頁了
實現滾動分頁查詢
需求:
- 查詢收件箱數據時,可以實現滾動分頁查詢
- 在個人主頁的 ”關注“ 卡片中,查詢并展示推送的Blog信息
具體操作
1、每次查詢完成后,我們要分析出查詢數據的最小時間戳,這個值會作為下一次的查詢條件
2、 我們需要找到與上一次查詢相同的查詢個數作為偏移量,下次查詢后,跳過這些查詢過的數據,拿到需要的數據
核心: 我們的請求參數中 就需要攜帶 lastId,上一次查詢的 最小時間戳 和 偏移量 這兩個參數
這兩個參數第一次由前端來指定,以后的查詢就根據后臺結果作為條件,再次傳遞給后臺。
核心源碼
一、定義出 具體的 返回實體類
@Data public class ScrollResult {private List<?> list;private Long minTime;private Integer offset; }BlogController
RequestParam 表示接受url地址欄傳參的注解,當方法上參數的名稱和url地址欄不相同時,可以通過RequestParam 來進行指定
@GetMapping("/of/follow") public Result queryBlogOfFollow(@RequestParam("lastId") Long max, @RequestParam(value = "offset", defaultValue = "0")Integer offset) {return blogService.queryBlogOfFollow(max, offset); }BlogServiceImpl
@Override public Result queryBlogOfFollow(Long max, Integer offset) {// 1.獲取當前用戶Long userId = UserHolder.getUser().getId();// 2.查詢收件箱 ZREVRANGEBYSCORE key Max Min LIMIT offset countString key = RedisConstants.FEED_KEY + userId;Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 2);// 3.非空判斷if (typedTuples == null || typedTuples.isEmpty()) {return Result.ok();}// 4.解析數據:blogId、minTime(時間戳)、offsetList<Long> ids = new ArrayList<>(typedTuples.size());long minTime = 0; // 2int os = 1; // 2for (ZSetOperations.TypedTuple<String> tuple : typedTuples) { // 5 4 4 2 2// 4.1.獲取idids.add(Long.valueOf(tuple.getValue()));// 4.2.獲取分數(時間戳)long time = tuple.getScore().longValue();if(time == minTime){os++;}else{minTime = time;os = 1;}}os = minTime == max ? os : os + offset;// 5.根據id查詢blogString idStr = StrUtil.join(",", ids);List<Blog> blogs = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();for (Blog blog : blogs) {// 5.1.查詢blog有關的用戶queryBlogUser(blog);// 5.2.查詢blog是否被點贊isBlogLiked(blog);}// 6.封裝并返回ScrollResult r = new ScrollResult();r.setList(blogs);r.setOffset(os);r.setMinTime(minTime);return Result.ok(r); }結果測試
?小結
以上就是【Bug 終結者】對 微服務Spring Boot 整合 Redis 實現好友關注 – Feed流實現推送到粉絲收件箱 的簡單介紹,微服務Spring Boot 整合 Redis 實現好友關注 – Feed流實現推送到粉絲收件箱功能也是 利用Set集合、ZSet集合實現這樣一個需求,同時,采用Redis來實現更加的快速,減少系統的消耗,更加快速的實現數據展示!
如果這篇【文章】有幫助到你,希望可以給【Bug 終結者】點個贊👍,創作不易,如果有對【后端技術】、【前端領域】感興趣的小可愛,也歡迎關注?????? 【Bug 終結者】??????,我將會給你帶來巨大的【收獲與驚喜】💝💝💝!
總結
以上是生活随笔為你收集整理的微服务Spring Boot 整合 Redis 实现好友关注 – Feed流实现推送到粉丝收件箱的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos7升级内核重启问题:you
- 下一篇: gradle idea java ssm