美文网首页
一个交互统计需求记录

一个交互统计需求记录

作者: 西5d | 来源:发表于2019-04-27 15:50 被阅读0次

    好久没有写文章了,这篇介绍一个工作中遇到的功能和相关设计,其中涉及到的几个点还是值得深入考虑下,简单做个记录。

    业务场景

    实际是一个数据统计的需求,比如我们在使用微博的时候,会记录有多少人评论,发布多少评论,收到多少评论等交互信息。与之类似,这个需求详细描述的话有如下5个指标要提供。
    1、用户发布的内容数;
    2、用户内容得到的分享数
    3、用户分享的内容数;
    4、用户给他人的评论数;
    5、用户内容获得的评论数;

    概要设计

    问题一

    用户发布的内容数
    首先,第一个用户发布的内容数,这个其实只要在用户发布的时候做记录就可以了。这个是一种基础的方案,另外有一种场景是,这个发布的内容需要审核。内容只记录有效内容,这个场景下,有三种解决方法:1)如果有消息组件,在完成审核之后推送消息来统计。2)没有消息组件或者不完善可以用借口回调做统计。3)比较笨拙的方法,固定时间后主动调用接口获得统计数据。但是会有问题,审核如果是人工的,往往不会是固定周期完成,因此不推荐。操作其实就是分享之后给authorId 对应的pub_count+1。

    问题二

    用户内容获得的分享数
    这里俩问题,计数的是内容还是分享的人次,是否需要去重。这里我们看下,首先有三个关键参数,内容ID,分享者,内容作者,即contentId,sharedBy,authorId。用户内容获得的分享数,假设去重,就用 sharedBy + contentId 判断是否已经分享,否则设置标签并给对应的authorId的recv_shared_count + 1。当然这里如果是记录分享人次,则用authorId + sharedBy去重,效果就是只要用户A分享过B的内容,就算一人次计数,且以后再分享都不算。

    问题三

    用户分享的内容数
    这个比较简单,用sharedBy + contentId做去重,然后按结果给对应的sharedBy的shared_count+1

    问题四

    用户给他人的评论数
    这个是比较复杂的一个功能,有很多的情况。首先,评论一般是在一个内容下的,回复内容算作一级评论,当然还有回复评论,会有多级的评论回复。如果是统计人次,还有个场景就是A发内容,B评论A,C评论B的评论,这种情况到底算给谁的评论,这里我们默认也算作给A的评论,因为都是在A的内容下。还有一种比较特殊就是,在别人的内容下自己回复自己的评论是不是要计数,虽然这个情况比较少,其实也可以加但可能会有hash key 放大的风险,因为又增加了一个维度的统计。
    这个还是内容的评论数,不是用户评论了多少人,还是以内容来判断的。首先,发布评论之后,有几个参数:内容id,评论者,内容作者,即contentId,commenter,authorId,首先用authorId和commenter过滤自己给自己的评论。其次给对应的commenter的comment_count + 1

    问题五

    用户内容获得评论数
    这个还是以内容计数的,在评论的时候会有三个参数,评论者,内容作者,内容id,即commenter,authorId,contentId,首先过滤自己给自己内容评论(他人内容下自己回复自己评论不过滤),最后给对应的authorId的recv_comment_count+1。

    技术选型和设计

    具体要使用哪种技术,其实是和业务紧密相关的。首先我们可以看到类似exist和incr的操作,直观的是使用Redis,但Redis涉及到集群维护以及持久化的问题,如果有成熟的环境可以直接来用就方便了。持久化除了依赖Redis当然也可以自己维护,比如用任务刷到数据库等等。其次可以考虑MySQL持久化,如唯一键等特性,当然也可以自己维护逻辑关系。其他比如Pegasus等也可以使用。
    聪明的同学已经看到给别人评论和收到评论,以及分享别人内容和获得分享是有关联的。的确设计的时候这两种情况是在一起考虑的。以下是整体的设计方案和伪代码。
    1、结构

       pub_count;  //发布内容数
       shared_count;//分享内容数
       comment_count;//发布评论数
       recv_comment_count;//内容获得评论数
       recv_shared_count;//内容获得分享数
    }
    

    2、业务伪代码

    incrPubCount(authorId){
        incr(authorId+pub_count);
    }
    incrSharedCount(sharedBy,authorId,contentId){
        if(exist(sharedBy+contentId) || sharedBy == authorId){
          return;
       }else{
          set(sharedBy+contentId);
          incr(sharedBy+shared_count);
          incr(authorId+recv_shared_count);
       }
    }
    //具体按人次还是按内容依据情况修改。
    incrCommentCount(commenter,authorId,contentId){
           if(authorId == commenter){
                 return;
           }else{
               incr(commenter+comment_count);
               incr(authorId+recv_comment_count);
           }
    }
    
    

    总结

    以上就是回顾的所有内容,某些方面还是有待完善,比如数据量非常大的时候的存储选型;某些异常的时候状态可能不一致的问题,如:A分享B,A分享计数增加,但B获得分享计数增加失败的情况。这种问题其实非常典型,类似银行转账的,只是这个是两边都增加。也因为业务不需要这么严谨,而且主要是每个具体操作比较简单,可以看做是原子的,依赖服务失败几率比较小,失败后再重试或者回滚成功的可能也比较小,因此没有再做更复杂的容错方案。感兴趣的朋友可以再深入了解下一致性相关内容。
    还有一个是这个需求统计相关,可以用异步流程实现,如spring的async注解,以后有时间单独开篇文章介绍下。
    以上,感谢阅读。

    相关文章

      网友评论

          本文标题:一个交互统计需求记录

          本文链接:https://www.haomeiwen.com/subject/qzhknqtx.html