dot Redis 8 来了——而且是开源的

了解更多

如何构建一个可以使用 Redis 分析纽约市自行车流量模式的应用程序

花旗单车仍然是美国最受欢迎的自行车共享计划。在曼哈顿、布鲁克林、皇后区和布朗克斯区散布着 20,000 多辆自行车,从 A 到 B 从未如此简单。它便宜、方便且环保。

最值得注意的是,它很受欢迎。 感谢这个Launchpad 应用程序,您现在可以发现每天在不同时间,在城市的不同街区使用了多少自行车。 

尽管纽约提供其他交通方式,但那些致力于更健康、更环保的生活方式的人可以通过 NYC Bike 应用程序提前计划行程,了解他们在什么时间最有可能获得这些自行车之一。  

再一次,RedisGraph 是此应用程序的关键,它执行闪电般快速的查询,使用户能够可视化网络周围发生的流量模式。 让我们探索这是如何实现的。 

但在我们深入研究此应用程序的细节之前,我们想指出我们在 Launchpad 上有各种各样的应用程序供您查看。 

因此,请务必在阅读本文后浏览一下。 

https://www.youtube.com/embed/L7JiZFOp6Jg
  1. 你将构建什么?
  2. 你需要什么?
  3. 架构 
  4. 入门
  5. 它是如何工作的

1. 你将构建什么?

你将构建一个应用程序,该应用程序可以为用户提供纽约每个区域存在的不同交通模式的清晰详细的可视化效果。 使用 RedisGraph,用户将能够跨不同位置拖动地理空间索引,以揭示一段时间内花旗单车用户的精确数据。 

下面,我们将按有条不紊的顺序逐步介绍每个阶段,揭示每个组件应如何部署及其功能。 

什么是花旗单车?

从最纯粹的意义上讲,花旗单车是纽约最受欢迎的自行车租赁计划。 用户可以使用超过 20,000 辆自行车和 1,300 个站点,以廉价便捷的方式在城市中穿梭。 在这些自行车上从 A 到 B 很简单。 

使用乘车代码或会员密钥,你将能够解锁附近的自行车,并在你的会员资格有效期间随意进行短途骑行。 花旗单车覆盖了布朗克斯区、布鲁克林区、曼哈顿区和皇后区,覆盖了该市中心人口最密集的地区。 

2. 你需要什么?

  • RedisGraph 用作强大的图形数据库,可将 Cypher 查询转换为在 GraphBLAS 引擎上执行的矩阵运算。
  • Docker 用作用户轻松构建、部署和管理容器的平台。
  • 花旗单车行程数据 所有自行车行程数据都在网站上在线发布,供用户访问和下载。
  • React 用作 Javascript 库,可轻松构建用户界面。

3. 架构

架构流程

  • 客户端与用户界面交互并执行命令。 
  • 该应用程序使用 redismod Docker 镜像将数据传输到前端,该前端是用 React 构建的。 
  • React 使用声明式代码创建用户界面。 
  • 来自前端的图形查询由 Go 后端代理,该后端使用 redisgraph-go 库。
  • NGiNX 能够进行反向代理、缓存等,从而加速了应用程序交付。 
  • 然后,RedisGraph 会有效地稀疏矩阵,以向用户展示自行车数据。

4. 入门

先决条件

步骤 1. 安装先决条件

安装以下软件

  • Docker
  • Docker Compose

克隆存储库。 

https://github.com/redis-developer/nycbike

步骤 2. 创建 Mapbox 访问令牌 

单击 https://www.mapbox.com/ 创建一个新帐户 

单击 https://account.mapbox.com/access-tokens/  访问 MapBox 访问令牌

步骤 3. 复制访问令牌并将其添加到 .env 文件

运行以下命令将访问令牌复制到 frontend/.env

echo "REACT_APP_MAPBOX_ACCESS_TOKEN=<your-token>" > frontend/.env

构建可视化 UI 组件,并使用 Docker Compose 运行它们

$ docker build -t nycbike backend

步骤 4. 启动前端

$ cd frontend; npm install; npm run-script build; cd ..
$ docker-compose up

redismod_1  | 1:C 13 May 2021 03:12:18.017 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
 [...]
backend_1   | 2021/05/13 03:09:35 Connected to Redis!
backend_1   | 2021/05/13 03:09:55 Found 58070379 trips, 1638 stations, 818056 edges. Memory usage: 2.46G
backend_1   | 2021/05/13 03:09:55 Running app on port 3000...
 [...]
nginx_1     | 172.18.0.1 - - [13/May/2021:03:13:02 +0000] "GET /api/journey_query?src_lat=40.715653603071786&src_long=-73.98651260399838&src_radius=0.7&dst_lat=40.75472153232781&dst_long=-73.98468539999953&dst_radius=1.2 HTTP/1.1" 200 1328 "http://localhost/" "Mozilla/5.0"
 [...]

现在应该可以通过 http://localhost:80/ 访问前端,但由于 Redis 为空,因此地图将为空白。 

步骤 5. 运行容器

$ docker-compose up

结果

redismod_1  | 1:C 13 May 2021 03:12:18.017 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
 [...]
backend_1   | 2021/05/13 03:09:35 Connected to Redis!
backend_1   | 2021/05/13 03:09:55 Found 58070379 trips, 1638 stations, 818056 edges. Memory usage: 2.46G
backend_1   | 2021/05/13 03:09:55 Running app on port 3000...
 [...]
nginx_1     | 172.18.0.1 - - [13/May/2021:03:13:02 +0000] "GET /api/journey_query?src_lat=40.715653603071786&src_long=-73.98651260399838&src_radius=0.7&dst_lat=40.75472153232781&dst_long=-73.98468539999953&dst_radius=1.2 HTTP/1.1" 200 1328 "http://localhost/" "Mozilla/5.0"
 [...]

每次在 http://localhost:80/ 重新加载 UI 都应该显示这些行程的累积。 在实时演示中,有一个预构建的 dump.rdb,在磁盘上为 674MB。

将橙色圆圈拖动到其他位置,你可能会注意到 RedisGraph 显示 毫秒内的行程。

5. 它是如何工作的

花旗单车在线发布其所有行程数据,为用户提供有关此公共自行车系统的一些最常见问题的答案。 这些包括

  • 花旗单车骑手在哪里骑行?
  • 他们什么时候骑行?
  • 他们走多远?
  • 哪个车站最受欢迎?
  • 一周中的哪些天骑车最多?

该图对每次行程都有一个起点和一个终点。 这由地图上的两个圆圈突出显示,蓝色圆圈表示自行车出发的区域,红色圆圈表示旅程结束的区域。 每个圆圈内的交通流量在下面的图中描述。 

此应用程序的一个惊人功能是用户界面上的灵活性。 你可以将两个圆圈拖放到地图上的任何所需位置,以发现该区域的交通流量。 同样,你可以放大和缩小每个圆圈,并根据你的偏好决定其周长的大小。 

拖动每个圆圈时,RedisGraph 以闪电般的速度处理数据,为你提供每个区域的交通流量的详细概述,且在毫秒内完成。 如果你想提前制定计划并避免等待花旗单车的麻烦,这将非常方便。 

如何构建后端

Go 后端使用 redisgraph-go 库来代理来自前端的图形查询。 重要的是要强调 Go 库不支持新的 point() 类型,因此你可以添加 PR redisgraph-go#45 功能。  

要标记地图上的每个站点(/stations API 调用),你可以使用一个简单的 Cypher 查询来获取所有位置

ATCH (s:Station) RETURN s.loc

要计算图中所有边(/vitals API 调用的一部分),你可以使用不同的 Cypher 查询: 

MATCH (:Station)-[t:Trip]->(:Station) RETURN count(t)

最后,用于检索行程的主要 Cypher 查询(/journey_query API 调用)的形式为

MATCH (src:Station)<-[t:Trip]->(dst:Station)
WHERE distance(src.loc, point($src)) < $src_radius
  AND distance(dst.loc, point($dst)) < $dst_radius
RETURN
  (startNode(t) = src) as egress,
  sum(t.counts[0]) as h0_trip_count,
  ...

这匹配 $src 和 $dst 圆圈内的所有:站点,以及这些站点之间的所有行程边(在两个方向上)。 由于以下原因,这是一个快速查询

:Station.loc

 你将看到的返回出口,如果行程从 $src 开始,则为 true,如果行程从 $dst 开始,则为 false。 至于 UI 上显示的行程图,它是通过聚合这些:行程边上的属性来构建的,用于出口和入口流量。 

如何构建前端

前端是用 React 构建的,并且围绕 react-mapbox-gl 和已实施的自定义绘图模式。 聚合行程图是使用 devexpress/dx-react-chart 构建的。

Offline_importer

离线导入器下载公共 花旗单车行程数据,解压缩每个存档,并将所有行程编入行程图的索引。 该图包含每个:站点作为节点,站点 ID 上的索引,以及站点位置的地理空间索引

此 Cypher 查询将创建一个包含一次行程的新对冲,或者递增边上适当的计数器以索引该行程。 编写所有 5600 万次行程的最有效方法是使用流水线并为每个批次关闭 CLIENT REPLY OFF。 批量导入将花费几个小时。 

2021/05/12 22:58:56 [dww.0]: Flushing 10000 commands, 10000 trips
2021/05/12 22:59:01 [dww.0]: Flushing 10000 commands, 10000 trips
2021/05/12 22:59:05 [dww.0]: Flushing 10000 commands, 10000 trips

每次在 http://localhost:80/ 重新加载 UI 都会显示这些行程的累积。 在实时演示中,使用了预构建的 dump.rdb,在磁盘上为 674MB。 

结论:快速查询,清晰的交通模式

处理速度通常决定了应用程序的质量。 任何缓慢而令人不快的操作都会阻碍用户的体验,甚至会破坏创意应用程序的实现计划。 

Redis 以惊人的速度处理查询的能力使该应用程序能够充分发挥其潜力,从而显示每个指定区域的不同交通模式。因此,您可以在不同的街区之间自由切换,以发现交通流量并制定最佳路线。

您可以通过访问 Redis Launchpad 了解有关此创新应用程序的更多详细信息。在那里,您可能还想浏览我们提供的 一系列令人兴奋的应用程序

谁创建了这个应用程序?

Mitch Ward

Mitch 目前是 Datadog 的一名工程师。

请务必访问他的 GitHub 页面,查看他参与的所有最新项目。