21年的时候曾写过一篇文章分享了自己的知识管理方案,其中我将个人数据都存储在了第三方服务上。虽然第三方的服务很好用,但终究存在关服或无法访问导致的数据丢失风险,始终让我感到不放心;同时数据散落在各处,也没法进行统一备份管理、数据应用和数据可视化。
本着数据拿在自己手上才算安全的原则,同时也期望将数据汇聚在一起进行统一的访问存取使用,我动手构建了一套自己的数据中心解决方案,实现了对现有使用中的第三方数据服务的采集,以及数据采集以后的应用和可视化功能。在此基础上我还开发了一些属于我自己的数据产品,将某些不方便采集的第三方服务替代掉。
系统架构
本文将以阅读记录数据为例,分享系统的架构设计和技术选型,为大家提供一种方案思路,具体的实现方案可以参考文末的开发文档,关键的系统代码也都开源于GitHub,以供大家进行复现。
我首先将服务划分为第三方服务和部署在自己系统上的私有服务两类,系统架构的后端主要包括数据存储、定时任务调度、后端接口和报表系统四个模块。客户端的话使用微信机器人和Web服务,保证手机端和PC端都能直接访问。
对于数据中心来说最核心的部分就是数据存储了。在最开始的时候只是单纯的想备份各个平台上的数据,所以直接简单粗暴的存储为CSV文件,使用Pandas来进行数据处理。但到后来我又想进一步增加可视化和即席查询的需求时就感到很不方便了,最终还是上了MySQL。
为了便于未来服务器到期时数据库环境的迁移,我将MySQL安装在一个docker容器里,缺点就是对我那台已经部署了多个服务的1核2G的服务器来说跑起来略显吃力。不过好在只是个人使用,没有数据量和并发方面的压力。
当MySQL搭建起来以后,就已经具备了数据的存储和读写查询能力了,但是数据中心的搭建就只是搭建一个MySQL环境这么简单吗。我想对个人用户来说,如何减少开发成本,同时高效的进行数据读写和使用也是非常重要的。
数据采集
数据采集工具
在数据库搭建起来以后,接下来需要解决的首要问题是数据采集,数据中心没数据可怎么行。目前市面上各家厂商都研发了各种数据采集工具,开源的也有如Flume、Sqoop等,不过这些工具并不适合在个人用户场景使用。
好在之前选择各种云服务的时候都考虑到了数据导出的问题,目前主力使用的Notion数据库和LeanCloud数据库都提供了完善的API接口,编写简单的python代码就可以将数据备份导出。
数据采集方式
按照维度建模的思想,数据表可以划分为维度表和事实表:
- 维度表:通常记录客观世界的一个实体对象,如书单表中的一条记录存储一本书的相关属性信息信息;
- 事实表:通常记录实体对象的一个动作行为,往往会伴随着一个动作的发生时间,以及动作的相关度量值,如一次读书记录的开始、结束时间和阅读页数。
根据不同表的特点,我也分别采取不同的方式进行建模和数据采集:
- Notion的数据库拥有非常友好的用户交互界面,所以我喜欢用来创建数据量不大、更新频率低的维度表。每次调度任务全量同步到MySQL数据库中即可,MySQL中的维度表仅作只读、备份使用。
- 对于数据量较大、更新频繁的阅读记录表这类事实表则直接创建在MySQL数据库中,通过后端交互接口进行插入更新,逐条记录。
任务调度系统
数据采集任务通常是凌晨或者每小时定时执行,因此需要使用定时调度系统。开源的任务调度系统有Azkaban,可以直接在Web界面进行任务配置,不过对于我目前的任务数量和场景来说过于重量级了,暂时没有考虑使用。
在这里我直接选用Linux系统默认安装的crontab进行任务调度,优点是开箱即用,不需要复杂的配置;缺点是需要在服务器上进行任务配置。
为了解决这个问题我在crontab中配置分时刻调度一个指定的sh脚本,再在各个sh脚本中批量执行相应的采集任务脚本,之后我只需要在本地修改这个sh脚本和采集任务脚本,再通过git推送到远程服务器即可。
数据应用
数据交互端口
由于我们日常活动中无时无刻都在产生事实数据,这类数据繁多且更新频繁,即使只关注我们感兴趣的数据也还是太多,来的太频繁了。最好是有这么一个简单便捷的入口进行记录,否则一旦没有及时记录下来之后就很容易从脑中遗忘、丢失,或者因为记录过程过于繁琐而放弃记录。
在使用flomo和滴答清单的过程中我受到了启发,他们都提供了关注微信公众号发送消息的数据记录方式。将微信作为数据录入端口相较于我过去安装一堆用于记录阅读、影视、打卡等垂类数据记录应用来说不会过于增加用户的使用压力,所有数据都统一到一个端口进行录入。
同时从开发层面来说,通过文本交互的形式进行数据的使用和录入,几乎没有前端开发工作量,我只需要做好后端接口对微信发送来的消息进行相应的回应即可。
可能对于习惯了图形用户界面的读者来说使用文本交互不是很适应,但是对习惯了使用命令行的我来说非常高效。你可能会觉得从一条数据记录过程中的操作步骤来说,编辑一段文本要比点按几个按钮的工作量大得多,但我个人使用下来反倒感觉就像平时发送微信消息一样自然。由于只是个人使用,对于那些经常执行的命令也可以通过英文缩写等一些方式来进行简化,减少数据录入时的文本编辑量。同时长期使用后输入法的记忆功能也能起到常用命令的提示效果。
经过实际调研以后我发现,个人用户要注册一个公众号还是挺麻烦的一件事情,而微信本身并没有提供机器人服务。但是也并不是没有解决方案,我们可以使用企业微信机器人,企业微信的注册相较微信公众号来说也要简单得多,而且微信内部可以直接访问企业微信的会话;美中不足的是使用微信访问时需要比直接使用企业微信多进行一次跳转,不过我宁愿多跳转一下也不愿意去额外安装一个app,哈哈。
而在PC端两者并没有做融合,就只能单独安装一个企业微信了。不过如果企业微信没有别的使用需求的话,可以一直保持在机器人输入界面,配合Alfred等快捷启动工具可以快速呼出进行输入。
消息处理流程
第三方服务机器人的接口都是以文本的形式进行进行输入输出,所以在后端的设计上我划分为四个模块:
- 接收模块:负责对接个平台的机器人接口,接收前端传过来的消息;
- 分发模块:判断命令的类型,将其分发到对应的处理模块中进行处理;
- 处理模块:与数据库进行交互,完成数据的读写分析,可以实现对消息的各种业务流程处理,一个模块就是一个应用。在这里可以充分发挥自己的想象力,做任何想做的事情,也可以引入别人开发好的模块,就像给游戏打mod一样;
- 应答模块:将处理后的结果返回给前端显示。
如下图所示,该方案也可以迁移到同样提供类似API接口的钉钉机器人或其他第三方服务上,后端处理逻辑都是完全一样的,仅在消息接收和回复的过程略有不同。
数据可视化
当数据积累起来以后我们可以对其进行可视化和数据分析,进而对我们未来的行动决策提供指导帮助。
我的可视化方式有两种:
- 数据播报:周期性的通过定时任务在特定的时间向我汇报昨日或者最近一个时间周期的指标完成情况或未完成情况。
- 数据报表:通过圆饼图、折线图等图表的方式对数据进行分析展示。
通过对网上各种商用和开源的数据报表系统进行比较,我最终选择使用开源的Superset。虽然在功能上和商用的报表系统比有所欠缺,但是对于个人用户使用还是完全足够了。Superset通过网页进行访问,也能满足我全平台使用的需求。
Superset上还有一个我比较喜欢的功能是他的SQL Lab,可以随时随地的打开网页写几句SQL。出于安全限制,SQL Lab默认只开放查询语句执行权限,可以在高级设置中开启数据及数据表修改语句等执行权限,让我在很大程度上摆脱了Navicat等本地客户端。
至此,从数据产生、采集、存储、应用、分析和可视化的完整数据体系就完成了,不得不说要实现一套这样的系统对个人的开发能力还是有一定要求。如果读完本文觉得我的数据解决方案还不错的话,可以参考下面的资料进行实现:
- 服务端组件安装
- 数据采集模块
- 数据备份模块
- 微信机器人接入及后端开发
相关代码已托管于GitHub,欢迎Star!