学习

使用 Redis 构建分析仪表板应用程序

Ajeet Raina
作者
Ajeet Raina, 前 Redis 开发者增长经理

交互式分析仪表板有多种用途。它们使您能够共享数据,并为您提供所有这些至关重要的信息,以便更快地做出改变游戏规则的决策。使用传统的关联数据库构建实时动态仪表板可能需要一组复杂的查询。通过使用 Redis 等 NoSQL 数据库,您可以使用少量 Redis 命令构建功能强大的交互式动态仪表板。

Redis 是一个开源的、内存中的、键值数据存储,最常用于主要数据库、缓存、消息代理和队列。Redis 缓存提供亚毫秒的响应时间,使游戏、金融科技、广告科技、社交媒体、医疗保健和物联网等行业能够实现快速而强大的实时应用程序。本教程展示了一个用 NodeJS (JavaScript) 编写的基本分析仪表板应用程序,它使用 Redis Bitmap 数据类型。

步骤 1. 准备环境#

  • 安装 Node - v12.19.0
  • 安装 NPM - v6.14.8
  • 安装 Docker - v19.03.13 (可选)

步骤 2. 克隆存储库#

 git clone https://github.com/redis-developer/basic-analytics-dashboard-redis-bitmaps-nodejs

步骤 3. 设置后端#

首先我们将设置一些环境变量。

转到 /server 文件夹 (cd ./server),然后执行以下命令

 cp .env.example .env

步骤 4. 安装依赖项#

 npm install

步骤 5. 运行 Docker Compose 以安装 Redis#

 docker network create global
 docker-compose up -d --build

您可能需要在 docker 命令前加上 sudo。如果您不想使用 sudo,请创建一个名为 docker 的 Unix 组并将用户添加到该组。当 Docker 守护程序启动时,它会创建一个 Unix 套接字,该套接字可供 docker 组的成员访问。Redis 数据库启动并运行后,您可以使用 redis-cli 命令连接到它。

提示
  • 默认情况下,Redis 在端口 6379 上运行,但您可以通过在 docker compose 文件中指定备用主机端口来更改它。
  • 您可以使用 Redis 配置文件并将其作为卷挂载到 docker compose YAML 文件中。
  • 您可以使用 redis-cli -h hostname -p port 命令连接到 Redis 实例。
  • 您可以运行 Redis INFO 命令以从 Redis 实例获取统计信息、指标和运行状况信息,例如缓存、内存统计信息、Redis 指标和已启用的模块。
  • 使用 Redis MONITOR 命令实时查看客户端发送到 Redis 的命令。

步骤 6. 运行后端#

 npm run dev

步骤 7. 设置前端#

转到 /client 文件夹 (cd ./client),然后

 cp .env.example .env

步骤 8. 安装依赖项#

 npm install

步骤 9. 运行前端#

 npm run serve

它是如何工作的?#

数据如何存储?#

事件数据存储在各种键和各种数据类型中。

对于每个时间跨度

  • 年:如 2021
  • 月:如 2021-03 (表示 2021 年 3 月)
  • 日:如 2021-03-03 (表示 2021 年 3 月 3 日)
  • 月内周:如 2021-03/4 (表示 2021 年 3 月的第 4 周)
  • 任何时候

以及对于每个范围

  • 来源
  • 行动
  • 来源 + 行动
  • 行动 + 页面
  • 用户 ID + 行动
  • 全局

以及对于每种数据类型 (类型)

  • 计数 (存储为字符串的整数)
  • 位图
  • 集合

是生成的键,例如

 rab:{type}[:custom:{customName}][:user:{userId}][:source:{source}][:action:{action}][:page:{page}]:timeSpan:{timeSpan}

其中 [] 中的值是可选的。

  • 对于每个生成的键,例如 rab:count:*, 数据存储如下:INCR {key} 示例:
 INCR rab:count:action:addToCart:timeSpan:2015-12/3

对于每个生成的键,例如:rab:set:*, 数据存储如下:SADD {key} {userId} 示例

 SADD rab:set:action:addToCart:timeSpan:2015-12/3 8

对于每个生成的键,例如 rab:bitmap:*, 数据存储如下:SETBIT {key} {userId} 1. 示例

 SETBIT rab:bitmap:action:addToCart:timeSpan:2015-12/3 8 1

群组数据#

  • 我们存储注册的用户,然后购买了一些产品 (操作顺序很重要)。
  • 对于 12 月份的每次购买操作,我们检查用户是否之前执行过注册操作 (注册计数器必须大于零)。
  • 如果是,我们将用户位设置为 1,例如:SETBIT rab:bitmap:custom:cohort-buy:timeSpan:{timeSpan} {userId} 1
  • 例如,用户 ID 2 在 2015-12-17 购买了 2 件产品。它不会被存储。
  • 例如,用户 ID 10 在 2015-12-17 购买了 1 件产品,并在 2015-12-16 注册。它将存储如下:SETBIT rab:bitmap:custom:cohort-buy:timeSpan:2015-12 10 1。
  • 我们假设用户不能在没有注册的情况下购买。

保留数据#

  • 保留是指在两个不同日期购买产品的用户
  • 对于每次购买操作,我们检查用户是否在任何时候购买了比在特定日期购买的更多产品 (不包括当前购买)。
  • 如果是,我们将用户 ID 添加到集合中,例如:SADD rab:set:custom:retention-buy:timeSpan:{timeSpan} {userId}
  • 例如,用户 ID 5 在 2015-12-15 购买了 3 件产品。他的保留数据将不会被存储 (在特定日期购买的产品:2,在任何时间购买的产品:0)。
  • 例如,用户 ID 3 在 2015-12-15 购买了 1 件产品,之前在 2015-12-13 购买了 1 件产品。他的保留数据将被存储 (在特定日期购买的产品:0,在任何时间购买的产品:1),例如:SADD rab:set:custom:retention-buy:timeSpan:2015-12 3。

数据如何访问?#

  • 总流量:

12 月份: BITCOUNT rab:bitmap:custom:global:timeSpan:2015-12 X 12 月份的周: BITCOUNT rab:bitmap:custom:global:timeSpan:2015-12/{X} 示例

 BITCOUNT rab:bitmap:custom:global:timeSpan:2015-12/3
  • 每个页面的流量 ({page} 是以下之一:主页、产品 1、产品 2、产品 3):
December: BITCOUNT rab:bitmap:action:visit:page:{page}:timeSpan:2015-12

示例

 BITCOUNT rab:bitmap:action:visit:page:homepage:timeSpan:2015-12
  • 12 月份的第 X 周:
BITCOUNT rab:bitmap:action:visit:page:{page}:timeSpan:2015-12/{X}

示例

 BITCOUNT rab:bitmap:action:visit:page:product1:timeSpan:2015-12/2
  • 每个来源的流量 ({source} 是以下之一:google、Facebook、电子邮件、直接、推荐、无):

12 月份

BITCOUNT rab:bitmap:source:{source}:timeSpan:2015-12

示例

 BITCOUNT rab:bitmap:source:referral:timeSpan:2015-12
  • 12 月份的第 X 周: BITCOUNT rab:bitmap:source:{source}:timeSpan:2015-12/{X}

示例

 BITCOUNT rab:bitmap:source:google:timeSpan:2015-12/1
  • 趋势流量 ({page} 是以下之一:主页、产品 1、产品 2、产品 3):
  • 12 月份:从 BITCOUNT rab:bitmap:action:visit:{page}:timeSpan:2015-12-01 到 BITCOUNT rab:bitmap:action:visit:{page}:timeSpan:2015-12-31
  • 12 月份的第 1 周:与上面类似,但从 2015-12-01 到 2015-12-07
  • 12 月份的第 2 周:与上面类似,但从 2015-12-08 到 2015-12-14
  • 12 月份的第 3 周:与上面类似,但从 2015-12-15 到 2015-12-21
  • 12 月份的第 4 周:与上面类似,但从 2015-12-22 到 2015-12-28
  • 12 月份的第 5 周:与上面类似,但从 2015-12-29 到 2015-12-31
  • 示例:
 BITCOUNT rab:bitmap:action:visit:homepage:timeSpan:2015-12-29 => BITCOUNT rab:bitmap:action:visit:homepage:timeSpan:2015-12-30 => BITCOUNT rab:bitmap:action:visit:homepage:timeSpan:2015-12-31
  • 购买的总产品数量:
  • 12 月: GET rab:count:action:buy:timeSpan:2015-12
  • 12 月第 X 周: GET rab:count:action:buy:timeSpan:2015-12/{X} 例如:
 GET rab:count:action:buy:timeSpan:2015-12/1
  • 添加到购物车的总产品数量:

12 月: GET rab:count:action:addToCart:timeSpan:2015-12 12 月第 X 周: GET rab:count:action:addToCart:timeSpan:2015-12/{X} 例如

 GET rab:count:action:addToCart:timeSpan:2015-12/1
  • 购买产品的份额({productPage} 是 product1、product2、product3 中的其中一个):

12 月: GET rab:count:action:buy:page:{productPage}:timeSpan:2015-12 例如

 GET rab:count:action:buy:page:product3:timeSpan:2015-12

12 月第 X 周: GET rab:count:action:buy:page:{productPage}:timeSpan:2015-12/{X} 例如:

 GET rab:count:action:buy:page:product1:timeSpan:2015-12/2

客户和群组分析#

  • 注册的用户数量:BITCOUNT rab:bitmap:action:register:timeSpan:2015-12
  • 注册后购买的用户数量(顺序很重要):BITCOUNT rab:bitmap:custom:cohort-buy:timeSpan:2015-12
  • 流失率:(注册后购买的用户数量 / 注册的用户数量) * 100 [%]
  • 仅购买指定产品的客户({productPage} 是:product1、product2、product3 中的其中一个):
SMEMBERS rab:set:action:buy:page:{productPage}:timeSpan:2015-12

示例

 SMEMBERS rab:set:action:buy:page:product2:timeSpan:2015-12
  • 购买了 Product1 和 Product2 的客户:
SINTER rab:set:action:buy:page:product1:timeSpan:anytime rab:set:action:buy:page:product2:timeSpan:anytime
  • 客户留存率(在不同日期购买的客户):SMEMBERS rab:set:custom:retention-buy:timeSpan:anytime

参考资料#