自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用Redis和Python構(gòu)建一個(gè)共享單車的應(yīng)用程序

開發(fā) 后端 其他數(shù)據(jù)庫 Redis
學(xué)習(xí)如何使用 Redis 和 Python 構(gòu)建一個(gè)位置感知的應(yīng)用程序。我組合了可用的公開的共享單車數(shù)據(jù)、Python 編程語言以及開源的 Redis 內(nèi)存數(shù)據(jù)結(jié)構(gòu)服務(wù),用來索引和查詢地理空間數(shù)據(jù)。

[[249389]]

學(xué)習(xí)如何使用 Redis 和 Python 構(gòu)建一個(gè)位置感知的應(yīng)用程序。

我經(jīng)常出差。但不是一個(gè)汽車狂熱分子,所以當(dāng)我有空閑時(shí),我更喜歡在城市中散步或者騎單車。我參觀過的許多城市都有共享單車系統(tǒng),你可以租個(gè)單車用幾個(gè)小時(shí)。大多數(shù)系統(tǒng)都有一個(gè)應(yīng)用程序來幫助用戶定位和租用他們的單車,但對(duì)于像我這樣的用戶來說,在一個(gè)地方可以獲得可租賃的城市中所有單車的信息會(huì)更有幫助。

為了解決這個(gè)問題并且展示開源的強(qiáng)大還有為 Web 應(yīng)用程序添加位置感知的功能,我組合了可用的公開的共享單車數(shù)據(jù)、Python 編程語言以及開源的 Redis 內(nèi)存數(shù)據(jù)結(jié)構(gòu)服務(wù),用來索引和查詢地理空間數(shù)據(jù)。

由此誕生的共享單車應(yīng)用程序包含來自很多不同的共享系統(tǒng)的數(shù)據(jù),包括紐約市的 Citi Bike 共享單車系統(tǒng)(LCTT 譯注:Citi Bike 是紐約市的一個(gè)私營公共單車系統(tǒng)。在 2013 年 5 月 27 日正式營運(yùn),是美國***的公共單車系統(tǒng)。Citi Bike 的名稱有兩層意思。Citi 是計(jì)劃贊助商花旗銀行(CitiBank)的名字。同時(shí),Citi 和英文中“城市(city)”一詞的讀音相同)。它利用了花旗單車系統(tǒng)提供的 通用共享單車數(shù)據(jù)流General Bikeshare Feed,并利用其數(shù)據(jù)演示了一些使用 Redis 地理空間數(shù)據(jù)索引的功能。 花旗單車數(shù)據(jù)可按照 花旗單車數(shù)據(jù)許可協(xié)議 提供。

通用共享單車數(shù)據(jù)流規(guī)范

通用共享單車數(shù)據(jù)流規(guī)范General Bikeshare Feed Specification(GBFS)是由 北美共享單車協(xié)會(huì) 開發(fā)的 開放數(shù)據(jù)規(guī)范,旨在使地圖程序和運(yùn)輸程序更容易的將共享單車系統(tǒng)添加到對(duì)應(yīng)平臺(tái)中。 目前世界上有 60 多個(gè)不同的共享系統(tǒng)使用該規(guī)范。

Feed 流由幾個(gè)簡單的 JSON 數(shù)據(jù)文件組成,其中包含系統(tǒng)狀態(tài)的信息。 Feed 流以一個(gè)*** JSON 文件開頭,其引用了子數(shù)據(jù)流的 URL:

  1. {
  2. "data": {
  3. "en": {
  4. "feeds": [
  5. {
  6. "name": "system_information",
  7. "url": "https://gbfs.citibikenyc.com/gbfs/en/system_information.json"
  8. },
  9. {
  10. "name": "station_information",
  11. "url": "https://gbfs.citibikenyc.com/gbfs/en/station_information.json"
  12. },
  13. . . .
  14. ]
  15. }
  16. },
  17. "last_updated": 1506370010,
  18. "ttl": 10
  19. }

***步是使用 system_informationstation_information 的數(shù)據(jù)將共享單車站的信息加載到 Redis 中。

system_information 提供系統(tǒng) ID,系統(tǒng) ID 是一個(gè)簡短編碼,可用于為 Redis 鍵名創(chuàng)建命名空間。 GBFS 規(guī)范沒有指定系統(tǒng) ID 的格式,但確保它是全局唯一的。許多共享單車數(shù)據(jù)流使用諸如“coastbikeshare”,“boisegreenbike” 或者 “topekametro_bikes” 這樣的短名稱作為系統(tǒng) ID。其他的使用常見的有地理縮寫,例如 NYC 或者 BA,并且使用通用唯一標(biāo)識(shí)符(UUID)。 這個(gè)共享單車應(yīng)用程序使用該標(biāo)識(shí)符作為前綴來為指定系統(tǒng)構(gòu)造唯一鍵。

station_information 數(shù)據(jù)流提供組成整個(gè)系統(tǒng)的共享單車站的靜態(tài)信息。車站由具有多個(gè)字段的 JSON 對(duì)象表示。車站對(duì)象中有幾個(gè)必填字段,用于提供物理單車站的 ID、名稱和位置。還有幾個(gè)可選字段提供有用的信息,例如最近的十字路口、可接受的付款方式。這是共享單車應(yīng)用程序這一部分的主要信息來源。

建立數(shù)據(jù)庫

我編寫了一個(gè)示例應(yīng)用程序 loadstationdata.py,它模仿后端進(jìn)程中從外部源加載數(shù)據(jù)時(shí)會(huì)發(fā)生什么。

查找共享單車站

GitHub 上 GBFS 倉庫中的 systems.csv 文件開始加載共享單車數(shù)據(jù)。

倉庫中的 systems.csv 文件提供已注冊的共享單車系統(tǒng)及可用的 GBFS 數(shù)據(jù)流的發(fā)現(xiàn) URLdiscovery URL。 這個(gè)發(fā)現(xiàn) URL 是處理共享單車信息的起點(diǎn)。

load_station_data 程序獲取系統(tǒng)文件中找到的每個(gè)發(fā)現(xiàn) URL,并使用它來查找兩個(gè)子數(shù)據(jù)流的 URL:系統(tǒng)信息和車站信息。 系統(tǒng)信息提供提供了一條關(guān)鍵信息:系統(tǒng)的唯一 ID。 (注意:系統(tǒng) ID 也在 systems.csv 文件中提供,但文件中的某些標(biāo)識(shí)符與數(shù)據(jù)流中的標(biāo)識(shí)符不匹配,因此我總是從數(shù)據(jù)流中獲取標(biāo)識(shí)符。)系統(tǒng)上的詳細(xì)信息,比如共享單車 URL、電話號(hào)碼和電子郵件, 可以在程序的后續(xù)版本中添加,因此使用 ${system_id}:system_info 這個(gè)鍵名將數(shù)據(jù)存儲(chǔ)在 Redis 中。

載入車站數(shù)據(jù)

車站信息提供系統(tǒng)中每個(gè)車站的數(shù)據(jù),包括該系統(tǒng)的位置。load_station_data 程序遍歷車站數(shù)據(jù)流中的每個(gè)車站,并使用 ${system_id}:station:${station_id} 形式的鍵名將每個(gè)車站的數(shù)據(jù)存儲(chǔ)到 Redis 中。 使用 GEOADD 命令將每個(gè)車站的位置添加到共享單車的地理空間索引中。

更新數(shù)據(jù)

在后續(xù)運(yùn)行中,我不希望代碼從 Redis 中刪除所有 Feed 數(shù)據(jù)并將其重新加載到空的 Redis 數(shù)據(jù)庫中,因此我仔細(xì)考慮了如何處理數(shù)據(jù)的原地更新。

代碼首先加載所有需要系統(tǒng)在內(nèi)存中處理的共享單車站的信息數(shù)據(jù)集。 當(dāng)加載了一個(gè)車站的信息時(shí),該站就會(huì)按照 Redis 鍵名從內(nèi)存中的車站集合中刪除。 加載完所有車站數(shù)據(jù)后,我們就剩下一個(gè)包含該系統(tǒng)所有必須刪除的車站數(shù)據(jù)的集合。

程序迭代處理該數(shù)據(jù)集,并創(chuàng)建一個(gè)事務(wù)刪除車站的信息,從地理空間索引中刪除該車站的鍵名,并從系統(tǒng)的車站列表中刪除該車站。

代碼重點(diǎn)

示例代碼中有一些值得注意的地方。 首先,使用 GEOADD 命令將所有數(shù)據(jù)項(xiàng)添加到地理空間索引中,而使用 ZREM 命令將其刪除。 由于地理空間類型的底層實(shí)現(xiàn)使用了有序集合,因此需要使用 ZREM 刪除數(shù)據(jù)項(xiàng)。 需要注意的是:為簡單起見,示例代碼演示了如何在單個(gè) Redis 節(jié)點(diǎn)工作; 為了在集群環(huán)境中運(yùn)行,需要重新構(gòu)建事務(wù)塊。

如果你使用的是 Redis 4.0(或更高版本),則可以在代碼中使用 DELETEHMSET 命令。 Redis 4.0 提供 UNLINK 命令作為 DELETE 命令的異步版本的替代。 UNLINK 命令將從鍵空間中刪除鍵,但它會(huì)在另外的線程中回收內(nèi)存。 在 Redis 4.0 中 HMSET 命令已經(jīng)被棄用了而且 HSET 命令現(xiàn)在接收可變參數(shù)(即,它接受的參數(shù)個(gè)數(shù)不定)。

通知客戶端

處理結(jié)束時(shí),會(huì)向依賴我們數(shù)據(jù)的客戶端發(fā)送通知。 使用 Redis 發(fā)布/訂閱機(jī)制,通知將通過 geobike:station_changed 通道和系統(tǒng) ID 一起發(fā)出。

數(shù)據(jù)模型

在 Redis 中構(gòu)建數(shù)據(jù)時(shí),最重要的考慮因素是如何查詢信息。 共享單車程序需要支持的兩個(gè)主要查詢是:

  • 找到我們附近的車站
  • 顯示車站相關(guān)的信息

Redis 提供了兩種主要數(shù)據(jù)類型用于存儲(chǔ)數(shù)據(jù):哈希和有序集。 哈希類型很好地映射到表示車站的 JSON 對(duì)象;由于 Redis 哈希不使用固定的數(shù)據(jù)結(jié)構(gòu),因此它們可用于存儲(chǔ)可變的車站信息。

當(dāng)然,在地理位置上尋找站點(diǎn)需要地理空間索引來搜索相對(duì)于某些坐標(biāo)的站點(diǎn)。 Redis 提供了幾個(gè)使用有序集數(shù)據(jù)結(jié)構(gòu)構(gòu)建地理空間索引的命令。

我們使用 ${system_id}:station:${station_id} 這種格式的鍵名存儲(chǔ)車站相關(guān)的信息,使用 ${system_id}:stations:location 這種格式的鍵名查找車站的地理空間索引。

獲取用戶位置

構(gòu)建應(yīng)用程序的下一步是確定用戶的當(dāng)前位置。 大多數(shù)應(yīng)用程序通過操作系統(tǒng)提供的內(nèi)置服務(wù)來實(shí)現(xiàn)此目的。 操作系統(tǒng)可以基于設(shè)備內(nèi)置的 GPS 硬件為應(yīng)用程序提供定位,或者從設(shè)備的可用 WiFi 網(wǎng)絡(luò)提供近似的定位。

查找車站

找到用戶的位置后,下一步是找到附近的共享單車站。 Redis 的地理空間功能可以返回用戶當(dāng)前坐標(biāo)在給定距離內(nèi)的所有車站信息。 以下是使用 Redis 命令行界面的示例。

想象一下,我正在紐約市第五大道的蘋果零售店,我想要向市中心方向前往位于西 37 街的 MOOD 布料店,與我的好友 Swatch 相遇。 我可以坐出租車或地鐵,但我更喜歡騎單車。 附近有沒有我可以使用的單車共享站呢?

蘋果零售店位于 40.76384,-73.97297。 根據(jù)地圖顯示,在零售店 500 英尺半徑范圍內(nèi)(地圖上方的藍(lán)色)有兩個(gè)單車站,分別是陸軍廣場中央公園南單車站和東 58 街麥迪遜單車站。

我可以使用 Redis 的 GEORADIUS 命令查詢 500 英尺半徑范圍內(nèi)的車站的 NYC 系統(tǒng)索引:

  1. 127.0.0.1:6379> GEORADIUS NYC:stations:location -73.97297 40.76384 500 ft
  2. 1) "NYC:station:3457"
  3. 2) "NYC:station:281"

Redis 使用地理空間索引中的元素作為特定車站的元數(shù)據(jù)的鍵名,返回在該半徑內(nèi)找到的兩個(gè)共享單車站。 下一步是查找兩個(gè)站的名稱:

  1. 127.0.0.1:6379> hget NYC:station:281 name
  2. "Grand Army Plaza & Central Park S"
  3.  
  4. 127.0.0.1:6379> hget NYC:station:3457 name
  5. "E 58 St & Madison Ave"

這些鍵名對(duì)應(yīng)于上面地圖上標(biāo)識(shí)的車站。 如果需要,可以在 GEORADIUS 命令中添加更多標(biāo)志來獲取元素列表,每個(gè)元素的坐標(biāo)以及它們與當(dāng)前點(diǎn)的距離:

  1. 127.0.0.1:6379> GEORADIUS NYC:stations:location -73.97297 40.76384 500 ft WITHDIST WITHCOORD ASC
  2. 1) 1) "NYC:station:281"
  3. 2) "289.1995"
  4. 3) 1) "-73.97371262311935425"
  5. 2) "40.76439830559216659"
  6. 2) 1) "NYC:station:3457"
  7. 2) "383.1782"
  8. 3) 1) "-73.97209256887435913"
  9. 2) "40.76302702144496237"

查找與這些鍵名關(guān)聯(lián)的名稱會(huì)生成一個(gè)我可以從中選擇的車站的有序列表。 Redis 不提供方向和路線的功能,因此我使用設(shè)備操作系統(tǒng)的路線功能繪制從當(dāng)前位置到所選單車站的路線。

GEORADIUS 函數(shù)可以很輕松的在你喜歡的開發(fā)框架的 API 里實(shí)現(xiàn),這樣就可以向應(yīng)用程序添加位置功能了。

其他的查詢命令

除了 GEORADIUS 命令外,Redis 還提供了另外三個(gè)用于查詢索引數(shù)據(jù)的命令:GEOPOS、GEODISTGEORADIUSBYMEMBER。

GEOPOS 命令可以為 地理哈希geohash 中的給定元素提供坐標(biāo)(LCTT 譯注:geohash 是一種將二維的經(jīng)緯度編碼為一位的字符串的一種算法,常用于基于距離的查找算法和推薦算法)。 例如,如果我知道西 38 街 8 號(hào)有一個(gè)共享單車站,ID 是 523,那么該站的元素名稱是 NYC:station:523。 使用 Redis,我可以找到該站的經(jīng)度和緯度:

  1. 127.0.0.1:6379> geopos NYC:stations:location NYC:station:523
  2. 1) 1) "-73.99138301610946655"
  3. 2) "40.75466497634030105"

GEODIST 命令提供兩個(gè)索引元素之間的距離。 如果我想找到陸軍廣場中央公園南單車站與東 58 街麥迪遜單車站之間的距離,我會(huì)使用以下命令:

  1. 127.0.0.1:6379> GEODIST NYC:stations:location NYC:station:281 NYC:station:3457 ft
  2. "671.4900"

***,GEORADIUSBYMEMBER 命令與 GEORADIUS 命令類似,但該命令不是采用一組坐標(biāo),而是采用索引的另一個(gè)成員的名稱,并返回以該成員為中心的給定半徑內(nèi)的所有成員。 要查找陸軍廣場中央公園南單車站 1000 英尺范圍內(nèi)的所有車站,請(qǐng)輸入以下內(nèi)容:

  1. 127.0.0.1:6379> GEORADIUSBYMEMBER NYC:stations:location NYC:station:281 1000 ft WITHDIST
  2. 1) 1) "NYC:station:281"
  3. 2) "0.0000"
  4. 2) 1) "NYC:station:3132"
  5. 2) "793.4223"
  6. 3) 1) "NYC:station:2006"
  7. 2) "911.9752"
  8. 4) 1) "NYC:station:3136"
  9. 2) "940.3399"
  10. 5) 1) "NYC:station:3457"
  11. 2) "671.4900"
雖然此示例側(cè)重于使用 Python 和 Redis 來解析數(shù)據(jù)并構(gòu)建共享單車系統(tǒng)位置的索引,但可以很容易地衍生為定位餐館、公共交通或者是開發(fā)人員希望幫助用戶找到的任何其他類型的場所。
責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2021-07-14 17:39:46

ReactRails API前端組件

2023-09-21 08:00:00

ChatGPT編程工具

2010-07-12 10:11:27

ibmdwWeb

2021-10-29 16:18:14

Streamlit Python

2024-02-26 00:01:01

RedisGolang應(yīng)用程序

2011-05-11 10:58:39

iOS

2021-02-17 11:05:34

PythonPyQt代碼

2024-01-09 18:00:22

Rust后端slvelte

2010-01-08 12:14:44

ibmdwAndroid

2024-12-24 08:12:59

2024-06-07 08:25:16

2012-03-30 15:54:43

ibmdw

2020-10-11 20:54:39

Python開發(fā)Docker

2022-02-18 08:43:19

Spring Boo應(yīng)用程序RabbitMQ

2021-04-03 12:31:48

Python開發(fā)數(shù)據(jù)科學(xué)

2009-01-03 14:25:10

ibmdwWeb

2019-05-27 13:50:35

多云架構(gòu)企業(yè)多云集成云計(jì)算

2010-06-13 09:22:37

jQuery

2011-03-14 15:14:10

AzureFacebook營銷式應(yīng)用程序

2011-03-14 14:47:50

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)