dot 速度的未来将在你所在的城市举办的活动中出现。

加入我们在 Redis Released

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

Citi Bike 仍然是美国最受欢迎的自行车共享计划。曼哈顿、布鲁克林、皇后区和布朗克斯拥有超过 20,000 辆自行车,从 A 点到 B 点从未如此轻松。它价格便宜、方便,而且环保。

最值得注意的是,它很受欢迎。借助此 Launchpad 应用程序,您现在可以了解在城市不同社区的每天不同时间使用了多少辆自行车。

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

RedisGraph 再次成为此应用程序的核心,它执行闪电般的快速查询,使用户能够可视化网络周围发生的交通模式。让我们来探讨一下它是如何实现的。

但在深入探讨此应用程序的具体细节之前,我们想指出,我们在 Launchpad 上提供各种应用程序供您查看。

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

https://www.youtube.com/embed/L7JiZFOp6Jg
  1. 您将构建什么?
  2. 您需要什么?
  3. 架构
  4. 入门
  5. 工作原理

1. **您将构建什么?**

您将构建一个应用程序,可以为用户提供清晰详细的纽约市每个区域不同交通模式的可视化。使用 RedisGraph,用户将能够在不同位置拖动地理空间索引,以发现一段时间内 Citi Bike 用户数量的精确数字。

下面我们将按顺序逐步引导您完成每个阶段,揭示每个组件应如何部署及其功能。

什么是 Citi Bike?

从最纯粹的意义上来说,Citi Bike 是纽约市最受欢迎的自行车租赁计划。用户可以访问超过 20,000 辆自行车和 1,300 个站点,作为一种廉价便捷的城市出行方式。骑着这些自行车从 A 点到 B 点非常简单。

使用乘车代码或会员密钥,您将能够解锁附近的自行车,并在您的会员资格有效期间进行任意次数的短途骑行。Citi Bike 覆盖了布朗克斯、布鲁克林、曼哈顿和皇后区,涵盖了城市中心的大部分人口稠密区域。

2. **您需要什么?**

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

3. **架构**

架构流程

  • 客户端与用户界面交互并执行命令。
  • 该应用程序使用 redismod Docker 镜像将数据传输到使用 React 构建的前端。
  • React 使用声明式代码创建用户界面。
  • 来自前端的图查询由 Go 后端代理,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. **工作原理**

Citi Bike 在线发布了所有行程数据,为用户提供了一些关于该公共自行车系统的最常见问题的答案。这些问题包括

  • Citi Bike 骑行者在哪里骑车?
  • 他们什么时候骑车?
  • 他们骑行多远?
  • 哪些站点最受欢迎?
  • 一周中哪些天进行的骑行次数最多?

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

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

当您拖动每个圆圈时,RedisGraph 会以闪电般的速度处理数据,在几毫秒内为您提供每个区域交通流量的详细概述。如果您想提前制定计划并避免等待 Citi Bike 的麻烦,这非常方便。

如何构建后端

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 圆圈内的 :Stations,以及这些站点之间所有行程边(双向)。由于以下原因,这是一个快速查询:地理空间索引

:Station.loc

返回的 egress 如果行程从 $src 开始,则为 true,如果行程从 $dst 开始,则为 false。关于在 UI 上呈现的行程图,它是通过汇总这些 :Trip 边的属性来构建的,用于出口和入口流量。

如何构建前端

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

离线导入器

离线导入器下载公共 Citi Bike 行程数据,解压缩每个存档,并将所有行程索引到旅程图中。该图包含每个 :Station 作为节点,一个站点 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 页面,查看他参与的所有最新项目。