redis的用法,Redis——實現關注與取關等功能

 2023-10-15 阅读 29 评论 0

摘要:目錄 實現關注與取關 實現共同關注功能 關注推送 Feed流的模式 拉模式 推模式 推拉結合模式 總結 基于推模式實現關注推送功能 Feed流的分頁問題 實現關注推送頁面的分頁查詢 實現關注與取關 實現 redis的用法。Controller層 @RestController @RequestMapping("/f

目錄

實現關注與取關

實現共同關注功能

關注推送

Feed流的模式

拉模式

推模式

推拉結合模式

總結

基于推模式實現關注推送功能

Feed流的分頁問題

實現關注推送頁面的分頁查詢


實現關注與取關

實現

redis的用法。Controller層

@RestController
@RequestMapping("/follow")
public class FollowController {@Resourceprivate IFollowService followService;@PutMapping("/{id}/{isFollow}")public Result follow(@PathVariable("id")Long followUserId,@PathVariable("isFollow") Boolean isFollow){return followService.follow(followUserId,isFollow);}@GetMapping("/or/not/{id}")public Result follow(@PathVariable("id")Long followUserId){return followService.isFollow(followUserId);}
}

?

Service層

    @Overridepublic Result follow(Long followUserId, Boolean isFollow) {//1.獲取登錄用戶UserDTO user = UserHolder.getUser();Long userId = user.getId();//判斷是取關還是關注if(isFollow){//2.關注,新增數據Follow follow = new Follow();follow.setUserId(userId);follow.setFollowUserId(followUserId);follow.setCreateTime(LocalDateTime.now());boolean isSuccess = save(follow);}else{//取關,刪除數據//sql: delete from tb_follow where user_id = ? and follow_user_id = ?remove(new QueryWrapper<Follow>().eq("user_id",userId).eq("follow_user_id",followUserId));}return Result.ok();}@Overridepublic Result isFollow(Long followUserId) {//1.獲取用戶UserDTO user = UserHolder.getUser();Long userId = user.getId();//查詢是否關注//sql: select * from tb_follow where user_id = ? and follow_user_idInteger count = query().eq("user_id", userId).eq("follow_user_id", followUserId).count();return Result.ok(count>0);}


實現共同關注功能

redis清理策略?

?

修改前面的關注接口,關注的對象不僅僅存入數據庫中,還需存入redis中(共同關注功能需要set數據結構完成)?

修改

    @Overridepublic Result follow(Long followUserId, Boolean isFollow) {//1.獲取登錄用戶UserDTO user = UserHolder.getUser();Long userId = user.getId();String key = "follows:"+userId;//判斷是取關還是關注if(isFollow){//2.關注,新增數據Follow follow = new Follow();follow.setUserId(userId);follow.setFollowUserId(followUserId);follow.setCreateTime(LocalDateTime.now());
//修改部分boolean isSuccess = save(follow);if(isSuccess){//按關注用戶的id放入redis的set集合中stringRedisTemplate.opsForSet().add(key,followUserId.toString());}}else{//取關,刪除數據//sql: delete from tb_follow where user_id = ? and follow_user_id = ?
//修改部分boolean isSuccess = remove(new QueryWrapper<Follow>().eq("user_id", userId).eq("follow_user_id", followUserId));if(isSuccess){stringRedisTemplate.opsForSet().remove(key,followUserId.toString());}}return Result.ok();}

關注再取關對方有顯示嗎?

實現

Controller層

    @GetMapping("/common/{id}")public Result followCommons(@PathVariable("id")Long id){return followService.followCommons(id);}

?

怎么關閉快捷功能、Service層

    @Overridepublic Result followCommons(Long id) {//1.獲取當前用戶idLong userId = UserHolder.getUser().getId();String key1 = "follows:"+userId;//2.求交集String key2= "follows:"+id;Set<String> intersect = stringRedisTemplate.opsForSet().intersect(key1, key2);if(intersect==null||intersect.isEmpty()){//無共同關注return Result.ok(Collections.emptyList());}//解析id集合List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());//查詢用戶List<UserDTO> users = userService.listByIds(ids).stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());return Result.ok(users);}


關注推送

?

Feed流的模式

如何關閉借唄功能。?

拉模式

(msg后面數據為時間戳)如下所示,趙六收件箱一般是空的,只有在趙六在讀消息時才會來拉取他關注目標的發件箱,并按照時間排序

優點:節省內存空間,收件箱讀完以后,就不用了可以清理,所以消息只保存一份在發件人的發件箱中

關注關注、缺點:每次去讀消息時,都要去拉取再做排序,耗時時間長,讀取時間較

推模式

彌補拉模式的缺點,每次都會把消息發給每一個粉絲,并排序,等粉絲讀取

把關人,缺點:這種擴散方式,每次更新消息時,都會發給每個粉絲,所以內存占用率很高

推拉結合模式

普通人采取推模式

大V,活躍粉絲采用推模式,普通的粉絲采用拉模式

redis高級用法?

總結

?


基于推模式實現關注推送功能

redis基本用法、

?

Feed流的分頁問題

思考應該用Redis中哪種數據結構進行時間戳的排序?是sortedset還是list

????????list查詢數據只能按照角標查詢,或者首尾查詢,不支持滾動分頁

redis注解、????????sortedset按照score值排序,得出排名,如果按照排名查詢則跟角標查詢無區別,但是sortedset支持按照score值范圍進行查詢(把時間戳按照從大到小進行排列,每次排序都記住最小的時間戳,然后下次查詢時再找比這個時間戳更小的,這樣就實現了滾動分頁查詢)

小結:如果數據會有變化,盡量使用sortedset實現分頁查詢

采用傳統角標查詢會出現下列問題

?

?

使用滾動分頁,每次存入頁的最后一次角標

?

實現

Controller層

    @PostMappingpublic Result saveBlog(@RequestBody Blog blog) {return blogService.saveBlog(blog);}

Service層

    @Overridepublic Result saveBlog(Blog blog) {//獲取登錄用戶UserDTO user = UserHolder.getUser();blog.setUserId(user.getId());//2.保存筆記boolean isSuccess = save(blog);if(isSuccess == false){return Result.fail("新增筆記失敗!");}//3.查詢筆記作者所有粉絲//sql: 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推送sortedSetString key = "feed:" + userId;stringRedisTemplate.opsForZSet().add(key,blog.getId().toString(),System.currentTimeMillis());}//3.返回idreturn Result.ok(blog.getId());}

?


實現關注推送頁面的分頁查詢

角標查詢 和 通過記錄最后一個的范圍查詢的對比

一開始redis中z1集合存入的數據("m6" : 6,"m5" : 5,"m4" : 4,"m3" : 3,"m2" : 2,"m1" : 1)

實現滾動分頁查詢一定要傳入四個參數:

分數的最大值(max),分數的最小值(min),偏移量(offset),數量(count)(其中分數最小值,數量固定不變)

最大值每次都要找上一次查詢的最小分數(除了第一次)

偏移量(第一次采取0,以后采取1,小于等于與小于的區別)

注意:如果分數一樣會出現以下問題,所以offset應是上一次查詢的最小分數的總個數

?

接口說明

?

Controller層

@GetMapping("/of/follow")public Result queryBlogOfFollow(@RequestParam("lastId") Long max,@RequestParam(value = "offset",defaultValue = "0") Integer offset){return blogService.queryBlogOfFollow(max,offset);}

?

Service層

@Overridepublic Result queryBlogOfFollow(Long max, Integer offset) {//1.獲取當前用戶Long userId = UserHolder.getUser().getId();//2.查詢收件箱//ZREVRANGEBYSCORE key Max Min LIMIT offset countString key = "feed:" + userId;//元組Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 2);//非空判斷if(typedTuples==null||typedTuples.isEmpty()){return Result.ok();}//3.解析數據:blogId、minTime(時間戳)、offsetList<Long> ids = new ArrayList<>(typedTuples.size());long minTime = 0;int os = 1;//偏移量for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {//3.1獲取id(blogId)ids.add(Long.valueOf(typedTuple.getValue()));//3.2獲取分數(時間戳)//執行到最一定是最小時間戳long time = typedTuple.getScore().longValue();if(time == minTime){os++;}else{minTime = time;os = 1;}}//4。根據id查詢blog//不能采用下面方法查詢 in 語句無序//List<Blog> blogs = listByIds(ids);//應使用String idStr = StrUtil.join(",", ids);List<Blog> blogs = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();//5.封裝并返回//需要將blog的信息完善for (Blog blog : blogs) {//查詢blog相關用戶queryBlogUser(blog);//查詢blog是否被點贊isBlogLiked(blog);}ScrollResult scrollResult = new ScrollResult();scrollResult.setList(blogs);scrollResult.setOffset(offset);scrollResult.setMinTime(minTime);return Result.ok(scrollResult);}

?

?

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/144428.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息