zoukankan      html  css  js  c++  java
  • 使用redis完成简易网易云音乐后端

    网易云音乐功能分析
    1.存储所有歌曲(评论数)
    2.一首歌对应多个评论
    3.每个评论可以点赞 根据点赞数排序
    4.歌单 歌单中的歌曲已热度排序(评论数*432 + 喜欢这首歌的人*432 (比例还可以调整) + 发布时间)
    5.我喜欢的歌

    解决方案
    1.使用Hash存储歌的具体信息 使用String存储ID
    2.使用Set存储每首歌对应的评论ID
    3.使用ZSet
    4.使用Set存储歌曲ID
    5.使用java反射

    pojo:

    评论实体类
     1 public class Comment {
     2 
     3     private String id;
     4 
     5     private String comment;
     6 
     7     private String time;
     8 
     9     private String good;
    10 
    11     public Comment() {
    12     }
    13 
    14     public String getId() {
    15         return id;
    16     }
    17 
    18     public void setId(String id) {
    19         this.id = id;
    20     }
    21 
    22     public String getComment() {
    23         return comment;
    24     }
    25 
    26     public void setComment(String comment) {
    27         this.comment = comment;
    28     }
    29 
    30     public String getTime() {
    31         return time;
    32     }
    33 
    34     public void setTime(String time) {
    35         this.time = time;
    36     }
    37 
    38     public String getGood() {
    39         return good;
    40     }
    41 
    42     public void setGood(String good) {
    43         this.good = good;
    44     }
    45 }

    歌曲实体类

     1 public class Song {
     2 
     3     private String id;
     4 
     5     private String name;
     6 
     7     private String singer;
     8 
     9     private String comments;
    10 
    11     private List<Comment> commentList;
    12 
    13     public Song() {
    14     }
    15 
    16     public Song(String name, String singer) {
    17         this.name = name;
    18         this.singer = singer;
    19         this.comments = "0";
    20     }
    21 
    22     public String getId() {
    23         return id;
    24     }
    25 
    26     public void setId(String id) {
    27         this.id = id;
    28     }
    29 
    30     public String getName() {
    31         return name;
    32     }
    33 
    34     public void setName(String name) {
    35         this.name = name;
    36     }
    37 
    38     public String getSinger() {
    39         return singer;
    40     }
    41 
    42     public void setSinger(String singer) {
    43         this.singer = singer;
    44     }
    45 
    46     public String getComments() {
    47         return comments;
    48     }
    49 
    50     public void setComments(String comments) {
    51         this.comments = comments;
    52     }
    53 
    54     public List<Comment> getCommentList() {
    55         return commentList;
    56     }
    57 
    58     public void setCommentList(List<Comment> commentList) {
    59         this.commentList = commentList;
    60     }
    61 }


    新增歌曲
     1 // 新增歌曲
     2     private String addSong(Jedis conn, Song song) {
     3         // 获取歌曲ID
     4         // ID不存在会创建一个(1) 存在则会自增
     5         String id = String.valueOf(conn.incr("song:"));
     6 
     7         //将歌曲存入hash中
     8         String key = "song:" + id;
     9         HashMap<String, String> map = new HashMap<String, String>();
    10         map.put("id", id);
    11         map.put("name", song.getName());
    12         map.put("singer", song.getSinger());
    13         map.put("comments", String.valueOf(song.getComments()));
    14         conn.hmset(key, map);
    15 
    16         //记录热度 初始化成当前时间
    17         conn.zadd("hot:", now(), key);
    18         return id;
    19     }

    增加评论

     1 // 增加评论
     2     private void addComment(Jedis conn, String id, String comment) {
     3         String songKey = "song:" + id;
     4         //歌曲信息中评论还是加1
     5         conn.hincrBy(songKey, "comments", 1);
     6         //增加热度
     7         conn.zincrby("hot:", VOTE_SCORE, songKey);
     8 
     9         String commentKey = "song:" + id + " comments:";
    10 
    11         //获取评论id
    12         String commentID = String.valueOf(conn.incr(commentKey));
    13 
    14         commentKey += commentID;
    15 
    16         HashMap<String, String> map = new HashMap<String, String>();
    17         map.put("id", commentID);
    18         map.put("comment", comment);
    19         map.put("time", time());
    20         map.put("good", "0");
    21 
    22         conn.hmset(commentKey, map);
    23 
    24         //默认给自己点个赞
    25         conn.zadd("song:" + id + " score:", 1, "comments:" + commentID);
    26     }

    评论点赞

    1 //点赞
    2     private void good(Jedis conn, String song, String comment) {
    3         //增加点赞数(排名)
    4         conn.zincrby("song:" + song + " score:", 1, "comments:" + comment);
    5         //hash中记录
    6         conn.hincrBy("song:" + song + " comments:" + comment, "good", 1);
    7         //增加歌曲热度
    8         conn.zincrby("hot:", VOTE_SCORE, "song:" + song);
    9     }

    查询歌曲

     1 //按照热度获取歌曲
     2     private List<Song> song(Jedis conn) {
     3         Set<String> set = conn.zrevrange("hot:", 0, -1);
     4         List<Song> list = new ArrayList<>();
     5         for (String str : set) {
     6             list.add(get(conn.hgetAll(str), conn));
     7         }
     8         return list;
     9     }
    10 
    11     private Song get(Map<String, String> map, Jedis conn) {
    12         Class<Song> clazz = Song.class;
    13         Song song = null;
    14         try {
    15             song = clazz.newInstance();
    16         } catch (InstantiationException | IllegalAccessException e) {
    17             e.printStackTrace();
    18         }
    19         for (Map.Entry<String, String> entry : map.entrySet()) {
    20             try {
    21                 Field field = clazz.getDeclaredField(entry.getKey());
    22                 if (entry.getKey().equals("id")) {
    23                     String key = "song:" + entry.getValue() + " score:";
    24                     Set<String> set = conn.zrevrange(key, 0, -1);
    25                     List<Comment> list = new ArrayList<>();
    26                     for (String str : set) {
    27                         list.add(getComment(conn.hgetAll("song:" + entry.getValue() + " " + str)));
    28                     }
    29                     Field commentList = clazz.getDeclaredField("commentList");
    30                     commentList.setAccessible(true);
    31                     commentList.set(song, list);
    32                 }
    33                 field.setAccessible(true);
    34                 field.set(song, entry.getValue());
    35             } catch (IllegalAccessException | NoSuchFieldException e) {
    36                 e.printStackTrace();
    37             }
    38         }
    39         return song;
    40     }
    41 
    42     private Comment getComment(Map<String, String> map) {
    43         Class<Comment> clazz = Comment.class;
    44         Comment comment = null;
    45         try {
    46             comment = clazz.newInstance();
    47         } catch (InstantiationException | IllegalAccessException e) {
    48             e.printStackTrace();
    49         }
    50         for (Map.Entry<String, String> entry : map.entrySet()) {
    51             try {
    52                 Field field = clazz.getDeclaredField(entry.getKey());
    53                 field.setAccessible(true);
    54                 field.set(comment, entry.getValue());
    55             } catch (IllegalAccessException | NoSuchFieldException e) {
    56                 e.printStackTrace();
    57             }
    58         }
    59         return comment;
    60     }

    工具方法

    1 private long now() {
    2         return System.currentTimeMillis() / 1000;
    3     }
    4 
    5     private String time() {
    6         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    7         return df.format(new Date());
    8     }

     实验

     1 private static final int VOTE_SCORE = 432;
     2 
     3     private static Song[] songs = new Song[5];
     4 
     5     static {
     6         for (int i = 0; i < songs.length; i++) {
     7             songs[i] = new Song("1989" + i, "Taylor Swift" + i);
     8         }
     9     }
    10 
    11     public static void main(String[] args) {
    12         MyChapter01 chapter01 = new MyChapter01();
    13 
    14         Jedis conn = new Jedis("localhost");
    15         conn.select(10);
    16 
    17 //        for (Song song : songs) {
    18 //            chapter01.addSong(conn, song);
    19 //        }
    20 
    21 //        chapter01.addComment(conn, "6", "霉霉好棒");
    22 //        chapter01.addComment(conn, "6", "女神加油");
    23 
    24         //少写一个点赞验证的set hhh
    25         chapter01.good(conn, "6", "1");
    26 
    27         List<Song> list = chapter01.song(conn);
    28         for (Song song : list) {
    29             System.out.println(song);
    30         }
    31     }

    结果




  • 相关阅读:
    把Discuz!NT放在虚拟目录下
    表格样式
    页面CSS的问题,不懂中
    临时存储信息
    asp.net2.0事务
    repeater控件分成两列显示
    P2P的NAT研究
    javascript字符串trim的实现
    新浪微博OAUTH2验证
    新浪微博接口在safri下的bug
  • 原文地址:https://www.cnblogs.com/Gang-Bryant/p/10993729.html
Copyright © 2011-2022 走看看