拉巴力的纸皮箱


  • 首页

  • 标签

  • 归档

  • 关于

  • 搜索

也谈谈feed流的设计

发表于 2024-05-28

几年前也做过feed流相关的服务,虽然网上相关的文章很多,这里也做个人的简要记录和总结
方案并非原创,当时是参考其他业务团队的设计

  • 需求背景:做一个用户动态模块,可以发动态,可以关注别人动态,有推荐列表,有消息提醒(其实就是微博的基本功能)

实现逻辑流程

  • 整个feed流设计都是强依赖Redis来实现的,以下列出key设计和对应的功能模块

    • 粉丝的feed流 - 【feed_list_$userId】
      • member-$id_$userId_$type (score-addtime)
    • 粉丝的feed流为空标志 - 【【feed_list_empty_$userId】】- 防止每次请求都穿透到DB
    • 用户的活跃粉丝列表 - 【active_fans_list_$userId】
    • 用户的活跃属性 - 【active_user_status_${userId}】
    • 动态详情 - 【cache.user.dynamic_${dynamicId}】 - MGet获取
  • 数据库分表设计

    • 用户动态表 - 按用户id分库
    • 评论表 - 按动态id分库(根据业务,一般都是单个动态的所有评论)
    • 点赞表 - 按用户id分库(根据业务,一般都是动态列表中展示当前用户的点赞状态)
  • feed流使用sortset,score是addtime

  • 推模式,通过维护用户的活跃粉丝列表(有数量限制),推到粉丝的feed流

  • 拉模式,通过请求第一页或其他接口进行预加载,查询粉丝的关注人和对应动态(有数量限制),构建粉丝自己feed流

01.feed流 构建 整体流程

  • 用户发动态、删动态、关注和取关事件,都会对feed流有相应操作
  • 通过发布事件的设计进行业务逻辑解耦

用户发动态(推模式)

  1. 用户发布动态(写入DB)
  2. 查询用户的活跃粉丝列表(Redis)
  3. 写入粉丝的Feed流(Redis)
  4. 写入消息表

粉丝拉关注列表(拉模式)(请求第一页或其他接口,预加载)

  1. 获取feed流(Redis)
  2. 获取关注用户列表(RPC)(限制2000个粉丝)
  3. 获取关注人的动态数据(DB)(限制没人100条动态)
  4. 写入个人的Feed流(Redis)
  5. 成为活跃用户(Redis)

02.动态消息交互

  • 消息表 和 消息读取时间表(用于控制用户红点提示和读取消息列表的范围)
  • 消息表保存7天定时清除

03.feed流预加载策略(pull模式)

  • 。。。。
  • 将用户加入为活跃粉丝

04.动态新增、删除(push模式),活跃粉丝处理

  • 用户的活跃粉丝列表逻辑
    1. 拉取过feed流或发布过动态等操作的用户,都会设置成有活跃粉丝属性的用户
    2. RPC获取用户的粉丝列表,过滤掉非活跃用户,保存到用户的活跃粉丝列表
    3. 关注和取关事件,也更新活跃粉丝列表

05.关注、取关 事件 对feed流的处理

06.获取feed流

  • 有了前面的推拉模式,用户直接从redis获取feed流即可

07.动态类型版本设计

  • 随着动态类型的新增,客户端旧版本不支持新类型动态,需要过滤;

  • 目前feed流是存在redis的,直接过滤可能会导致旧版本数据为空,可以通过多版本动态来区分

  • 实现描述

    1. 用户获取feed流,根据客户端的版本号等信息,判断出客户端支持的feed版本,并构建对应的feed流
    2. 用户发布动态,构建用户存在的活跃动态版本的feed流(为了用户的新旧版本都兼容)

扩展

  • 很久之前做的一次实验
    • 取消了微信黑名单,没看到之前的人的朋友圈。说明微信朋友圈也是feed持久化的方式实现
    • 微博也是这样,之前关注过,取关后再恢复,内容也能恢复,说明feed表只是逻辑删(应该是存数据库表了)
  • 微博feed实现(猜测)
    1. 为每个用户保存他所有关注的用户的feed表数据
    2. 假如取关,则重写关注能恢复数据(逻辑删除)
    3. 但如果之前没关注的用户,则他之前的动态不会出现在feed表中

聊聊配置中心

发表于 2024-05-09

第一次接触配置中心,是快十年前了,那时的配置中心还没像现在那么多成熟的开源项目,很多公司都需要结合自身业务自研。

使用配置中心的好处

  1. 快速发布变更配置,实时生效
  2. 对于不复杂的系统或业务配置,可以避免写繁琐的后台,但又具备快速变更的功能
  3. 读取配置性能高,一般配置后,都是以内存变量的方式常驻在服务中,可以说读取配置几乎零成本

配置中心的核心-推送原理

这里主要讲一下个人实际接触的三种原理,其实从宏观本质上看,三种方案原理是一致的

  1. 第一家公司的配置中心自研方案,借助ZooKeeper的临时节点变更事件,从而实现实时推送

  1. 第二家公司的服务治理中心的实现方案,使用Netty使服务中心和各服务之间建立TCP长链接,从而实现配置推送

  2. 第三家公司使用Apollo开源项目作为配置中心,原理是使用HTTP的Long polling方案

  • 从原理的本质上看,三者都是通过保持TCP连接不断开,从而复用这个通道进行数据推送
  • 除了推送的实现很重要之外,后台管理系统的设计和客户端的SDK也很重要。因为光能实时推送是不够的,要让接入配置中心方便,以及能方便管理和发布配置也是很关键的。在这一点上,Apollo这个开源项目是很不错的。

业务开发中的术与道

发表于 2024-05-07

从事IT行业若干年,有时回首,不禁感叹,很多技术方案和日常生活息息相关,可以相互借鉴。

以下只是草稿,以后有缘再整理

以下每项并不是独立,而是相互重叠的

  • 从日常的工作中总结常用的套路,勤记录,提升后续的效率
  • 多开发一些能提高效率的小工具,逐步优化,并可以给其他同事使用
  • 抽时间回顾和总结
  • 对用户的业务数据感兴趣,并思考哪些技术优化值得做

技术追求

  • 提升自身和团队的水平、服务架构合理性和性能的考虑、提高开发效率和体验

定时任务使用UDS作为触发运行的通知方式

  • 基于架构的完全性考虑:不暴露非本机触发的机会
  • 基于架构的合理性考虑:复用已有服务的逻辑和资源,无需新开进程
  • 具体实现看:谈谈定时任务的原理和应用 - 使用域信号通知通知服务

代码质量

使用代码扫描工具

  • 比如Java的Sonar、Golang的golint等

单元测试

  • 及时发现新代码逻辑问题,以及发现避免误改动等
  • 提交代码检查并及时阻断

代码Review

  • 上面的事项自动化,比如和gitlab pipeline结合,在开发阶段就及时修正;
  • 后续代码review可以避免审核低级问题,提高效率

开发效率

脚本工具

  • 开发快速生成curl脚本的工具,便于快速定位问题,以及反馈时提供复现实例;

代码复用

通用组件抽象

  • apollo灰度工具
  • bi数据上报组件
  • 消息通知组件

业务组件抽象

  • 目前都流行微服务,但有很多上游的逻辑是可以复用的,可以抽象出来,通过代码库的方式复用

服务稳定

灰度工具

  • 为保证改动一旦出问题,降低影响,开发基于配置中心的灰度工具,可以根据业务属性进行灰度

性能优化

  • 使用wrk、pprof等工具分析优化

文档化

常规事情文档化

复杂事情文档化

业务开发中使用BI的海量数据处理能力

发表于 2024-04-25
  • BI的数据统计跑数结果一般是T+1生成的
  1. 实时性要求不高的功能,用于推荐等其他业务功能,可用于统计和监控等
  2. 对实时性要求高的功能,做后置的监控,及早发现逻辑错误

从Java转Go的个人体会

发表于 2024-04-07

这里仅从一个业务开发的角度谈谈体会,格局较低,仅做个人记录
编程语言是程序员接触和使用最多的工具
后端技术基础的深度是快速学习和适应新语言的关键

  • 基于对工作中接触过的几种编程语言及其部署架构的看法继续聊。

  • 截至目前,职业生涯五分之四的时间都是在使用Java。出于个人意愿和兴趣,以及行业的发展形势,也系统的自学了Go语言,并在个人的小项目实践。在一次意外的组织变动中,我转岗到了新团队,并开始使用Go,由于之前自己的自学基础,基本是无缝切换到新语言。可能是由于团队人员大部分是从Lua或PHP开始转Go的,在那里甚至感觉自己稍稍领先。

  • Go抽象业务比Java麻烦,代码不美观,但是它原生高并发,而且微服务下很多时候就一个后端服务,业务足够小,不需要复杂的设计模式等,并不需要像以前写大型Java应用这样做非常多的抽象,还能打二进制包,甚至还能保证一个团队所有人代码都是相同风格

  • 以下讲一些个人看法,比较乱甚至不正确,仅做个人记录

    1. 小型项目省内存
    2. 写命令行程序方便简单
    3. 现在绝大部分功能都有相应的官方库和开源库
    4. 运行无需环境依赖,直接打包成二进制可执行程序(Java现在也可以了,可能大部分业务场景下体积还较大)
    5. 支持交叉编译,不要特定平台
    6. 打包体积小(根据代码实际使用情况打包-这点是我一直苦苦寻找的)
      • Go语言中有未用代码消除和可执行文件瘦身机制。只有在程序执行路径上被调用的函数才会进入最终的可执行文件,未被调用的函数会被消除
      • Go未用代码消除与可执行文件瘦身
  • 为什么现在大多数人都会认为Java启动慢占内存呢?

    • 首先不是Java自身的原因,而是跟实际使用场景有关
    • 使用Java大多数用来做业务开发,也习惯引入很多依赖库,首当其冲就是SpringBoot等框架
    • 多数都是spring相关类、proxy/cglib,以及各种bean配置
    • 而且很多类都是在启动的时候初始化的
  • 微服务下的编程语言

    • 在K8S流行之前,Java通常是使用SpringCloud
    • 其实微服务相关技术,在K8S已经实现了
    • 无论是使用Go还是Java,目前都应该向K8S靠近
    • 还有一点,K8S本身就是用Go实现的

扩展

  • 体验Graalvm+SpringBoot+Java21构建原生程序

  • 在内存利用效率上,Go语言确实比Java做得更好,在4个不同的角度来总结

    • Golang与Java全方位对比总结
    1. Java的JIT策略比Golang的AOT策略
      • Java在运行时相比Golang多占用了一些内存。原因在于:
        • Java运行态中包含了一个完整的解释器、一个JIT编译期以及一个垃圾回收器,这会显著地增加内存。
        • Golang语言直接编译到机器码,运行态只包含机器码和一个垃圾回收器。
      • 因此Golang的运行态相对消耗内存较少。
    2. 内存分配和垃圾回收器
      • Java确实在起步占用上偏多,毕竟jvm需要更多内存做jit,默认的gc算法对内存要求偏高,但这不能代表后续占用仍然线性增长。如果目标是启动成百上千个内存需求较少的进程,那Java确实不擅长。
    3. 并发
      • 协程模型比线程模型更加节省内存。
    4. 反射
      • Golang的反射更加简单,导致框架的内存消耗Golang程序比Java程序优秀。主要是因为: Java的框架实现中大量使用反射,并使用hashmap缓存信息,这2个都是极度消耗内存的行为。 Golang的框架中也使用reflect、map。但是Golang是面向interface和值类型的,这导致Golang的反射模型要比Java的反射模型简单非常多,反射过程要产生的对象数量也少非常多。
  • 为什么一些已经选择 Java 的公司,现在又开始考虑使用 Go?

    • 为什么要用Go重写Dubbo?
    • 相较于 Java,Go 在启动速度、编译速度、内存使用和高并发(如协程)方面都有明显优势。所以,那些已经采用 Java 的公司现在也在考虑引入 Go。但要注意的是,目前这样的公司仍然是少数。另外,一些公司并没有严格规定技术栈的选择,因此新成立的部门或新业务团队可以自由选择,而他们可能更倾向于选择 Go 作为开发语言。
    • 小结: 总的来说,无论是选择 Java 还是 Go,都是有其合理性的。一家公司同时选择这两种语言也同样合理。尽管这样的公司占比不大,但 Java 与 Go 之间的交流需求仍然存在。

记录限免业务的经验

发表于 2024-04-06
  • 由于业务需要,比如歌曲,我们需要对部分歌曲开放限免的功能,而且需要限制开放限免的场景。比如这首歌在场景A免费,在场景B收费。

  • 先说正确的做法,下发另外一个字段比如free_token,通过这个字段判断业务来源,和判断是否可以免费。free_token是随着对应的场景查询时下发的,是变化的。即同一个歌曲的free_token不是唯一的。

  • 现在有另外一种情况,想对现有的业务做限免(前端业务是不认free_token的)。这时可以把歌曲id使用free_token的值来下发,后续通过歌曲id来判断是否符合限免。

    • 这样做有个前提,就是前端业务没有使用歌曲id来做唯一性的业务(因为这是歌曲id是变化的),比如收藏。所以使用这个方案,要充分测试,而且可能还有其他不兼容的场景。

职场中的“善于沟通”和“高情商”

发表于 2024-04-05

很多人普遍认为,不跟人起冲突,能得到别人满意的评价,那么就一定程度上证明他高情商以及沟通能力好。
然而,这种观点真的正确吗?在某些情况下,这样做是否必要呢?

  • 先说结论,在高人才密度的公司中,基本也应该确实是这样。因为大家能相互理解,目标是做正确的事,简明扼要节约时间提升沟通效率,尊重别人及尊重自己,对有能力的人表示钦佩并愿意向他们学习。

  • 相反在低密度人才的公司或者公司领导人不开明等情况下,情况就有所不同。举例来说,如果公司内部人际关系不够平等,或者产品地位高于技术。产品需求缺乏认真性和逻辑性,技术人员只能被动接受,甚至放任不管,那么这种沟通方式就变得有问题了。技术人员默默忍受、妥协,把自己变成产品的需求完善员,即使自己的时间被浪费也不可惜。

  • 当金钱和地位给予足够时,技术人员选择妥协也可以理解。否则,那简直就是对自己的不尊重。

这件事情你需要跟进吗?

发表于 2024-04-03

在工作中,大多数情况下,大家都喜欢积极跟进事情的人。但有时候,这事情你真的要跟进吗?

  • 关于这个问题,其实并不是0或1这么简单。很多时候取决于公司的工作氛围或者分工、以及你对自己的定位等情况。

  • 在工作中,在相当长的时间里,我执行力特别强的人。我的原则是事事有结论(不给别人挖坑,不让事情烂尾)。所以我会很积极的跟进事情。

  • 但渐渐的,我开始怀疑,有些事情是你需要跟进的吗?

  • 以技术人员为例。你需要把自己当项目经理那样跟进事情吗?答案是分情况。

  • 有些情况你需要跟到底,而有些情况你只需要尽你责任即可,毕竟你有更重要的事情去做,或者说你的价值不应该在这里虚耗。

以下情况可能需要你跟进

  1. 属于你自己责任范围内的事情
  2. 这个事情是你主导发起的事情,关于你绩效等
  3. 你的公司的范围就是要你做项目经理,而且你也能接受(精神损失费不够另说)
  4. 你个人有意愿通过这种方式发展自己的综合素质或人脉等等

其他情况不需要跟进到底

  1. 已经当天反馈结果并提供解决问题的方向
  2. 需求方并未声明事情的优先级,自身也未跟进(说明不重要,不要经常给别人做无用功)
  3. 技术侧不应该每件事都跟进那么深入,尽了自己的义务即可,毕竟要合理分工
  4. 关于管理人员:不能以治标不治本的方式解决问题,技术领导应该表明立场,也是以后类似问题的处理立场,而不是一味认怂服从,累死下面的兄弟,而且没啥成长,纯粹苦力活
  5. 关于自身的话语权:作为基层员工,有些事情就是推不动,这个大家都很清楚,做到及时反馈的义务即可

再浅谈接口的安全性和回调机制

发表于 2024-04-02

最近的工作原因,涉及到接口充权益的接口安全性问题,这里趁热再说说个人看法

  • 基于之前写的这篇使用回调机制提高接口安全性继续聊。上次扩展中提到是不是可以使用非对称加密,替换回调验证?目前我所负责的业务确实使用这种方式。

  • 业务中要对接多个渠道,渠道需要调业务的接口来加权益,为了安全性,目前的做法是由渠道自己生成RSA私钥,提供RSA公钥到业务这边。渠道使用私钥生成签名,业务这边则使用公钥解密验证,从而保证请求是合法的。

  • 其实这里还是有潜在漏洞,之前的文章也提到过,如何保证私钥不泄漏?虽然说保证私钥不泄漏是渠道自己的问题,但是多年的经验告诉我,大多数公司并没有很好的保存这些私钥的方法。按照我的猜想,这些私钥在公司内部会被经常拷贝发送,至少开发人员基本都有办法知道的。万一知道私钥的人后续离职了作恶呢?

  • 而我们经常对接一下小渠道,参差不齐。尽可能保证渠道的安全也是我们作为平台要积极考虑的问题。

  • 所以个人的看法,即使使用RSA保证签名的合法,还是要提供回调的能力,提供给渠道,通过二次校验保证知道私钥的人也无法直接从自己的私人客户端发起请求并成功加权益。毕竟回调的请求是到达渠道方的正式服务器,要在正式服务器上线恶意代码,靠谱的公司都有一定的限制和管控。

扩展

  • 接口一般都会分外网访问和内网访问,我们平常要注意避免只能内网访问的接口暴露给外网访问,因为大多数情况下,我们的内网接口会安全性低一点。

打工人心态应该是怎样的?

发表于 2024-04-02

先来两段经典的话:

一
为众人抱薪者,不可使其冻毙于风雪;
为大众谋福利者,不可使其孤军奋战;
为自由开路者,不可使其困顿于荆棘。

二
愿中国青年都摆脱冷气,只是向上走。
不要听自暴自弃者的话。
能做事的做事,能发声的发声。
有一份光,发一份热。
就令萤火一般,也可以在黑暗里发一点光。
不必等候炬火。

  • 迫于由于现实的压迫,大家普遍焦虑,也会在工作中认怂,即使是不合理不正确负能量的等等;

  • 这些其实都能理解,不管是迫于生活压力,还是对方给得实在太多等原因;

  • 但有时,希望我们可以

    • 我们只是个打工的,有些东西不必过度较真
    • 虽是打工但也人格独立和自尊,不必唯唯诺诺
    • 有自己的时间分配和生活,不必紧盯信息,实在紧急对方会打电话
    • 不必焦虑,事事回复,根据自身情况,适当保持高姿态
    • 换位思考,容人之度,当然容人不是纵容
    • 工作时专注和高质量,不浪费自己时间

Reference

<1…456…17>

166 日志
191 标签
RSS
© 2025 Kingson Wu
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4