做者簡介:戴嘉樂( Mr.Maple ) | 前百度高級研發工程師 | IPFS應用實踐者&佈道師| 我的網站:www.daijiale.cn 聯繫方式:微信號:daijiale6239。vue
打造地理位置信息與區塊鏈的關係對象模型,創建一套 人->位置->真實世界->傳遞信任->價值轉移->位置->人 的生態模型,實現用區塊鏈來索引真實世界的願景。mysql
經過GeoHash算法能夠大幅度提升在龐大位置數據中的檢索效率,同時爲應用提供便捷的緩存機制。redis
IPFS&Filecoin技術則能夠保證在一個可信的區塊鏈網絡中去大規模傳遞與海量位置信息相關聯的海量文件、數據集合,並保證傳遞過程當中數據的產權價值。算法
DDApp DDApp ( Data Decentered Application ):是一個數據去中心化應用的概念,介於傳統應用和去中心化應用之間,解決了DApp不能依賴中心化的API的問題,又保證部分須要去中心化場景下的數據,在與應用交互以外,還能夠獨立分佈部署、P2P傳輸。sql
IPFS IPFS全稱InterPlanetary File System,中文名:星際文件系統,是一個旨在建立持久且分佈式存儲和共享文件的網絡傳輸協議。它是一種內容可尋址的對等超媒體分發協議可讓網絡更快、更安全、更開放。它是一個面向全球的、是一個點對點的分佈式版本文件系統,試圖將全部具備相同文件系統的計算設備鏈接在一塊兒。數據庫
GeoHash Geohash是由Gustavo Niemeyer發明的公共域地理編碼系統,它將一個地理位置編碼成一串字母和數字。它是一種層次化的空間數據結構,將空間細分爲網格形狀的桶,是一種被稱爲z -階空間填充曲線的應用,下圖中就是GeoHash算法中經常使用的Peano曲線,一種四叉樹線性編碼方式。api
3)字符串類似的表示距離相近(特殊狀況後文闡述),這樣能夠利用字符串的前綴匹配來查詢附近的POI信息。以下兩個圖所示,一個在城區,一個在郊區,城區的GeoHash字符串之間比較類似,郊區的字符串之間也比較類似,而城區和郊區的GeoHash字符串類似程度要低些。緩存
例如,座標對(116.414597,39.955441),位於北京安定門附近,GeoHash後造成的值爲WX4G2。安全
咱們已經知道現有的GeoHash算法使用的是Peano空間填充曲線,這種曲線會產生突變,形成了編碼雖然類似但距離可能相差很大的問題,所以在基於我的位置查詢附近Poi信息時,首先篩選GeoHash編碼類似的POI點,而後進行實際距離計算,來規避算法突變所形成的偏差。bash
固然Geohash只是空間索引的一種方式,特別適合POI點數據,而對線Link、面數據採用R樹索引更有優點。
Geo Object Model
屬性 | 類型 | 備註 |
---|---|---|
geo_id | INT | 惟一標識 |
geo_address | STRING | 地址名 |
geo_lng | FLOAT | 位置經度 |
geo_lat | FLOAT | 位置緯度 |
geo_hash | STRING | 位置生成的GeoHash值 |
ipfs_hash | STRING | 所存數據的IpfsHash值 |
addGeoInfoByParam() | FUNCTION | 添加位置信息方法 |
getGeoInfoByParam() | FUNCTION | 獲取位置信息方法 |
mixGeoHashByParam() | FUNCTION | GeoHash生成算法 |
addIpfsDataByParam() | FUNCTION | 添加Ipfs數據方法 |
mixIpfsHashByParam() | FUNCTION | 關聯Ipfs數據方法 |
這是網友以 100萬 poi 數據查詢範圍 3km 內的點(最多取100條)的性能測試統計:
如下是各數據庫的對比狀況:
數據庫 | 耗時 | 區域查詢 | 多條件支持 |
---|---|---|---|
redis(3.2.8) | 1-10ms | 支持 | 不支持 |
mongo(3.4.4) | 10-50ms | 支持 | 支持 |
postgreSQL(9.6.2) | 3-8ms | 支持 | 支持 |
mysql(5.7.18) | 8-15ms | 支持 | 支持 |
綜合比較後,我的選擇了MySql 來進行後文Demo的支撐數據庫:
PS:
-- 表的結構 `geo_object`--CREATE TABLE `geo_object` (`geo_id` bigint(20) NOT NULL AUTO_INCREMENT,`geo_loc` point NOT NULL,`geo_address` varchar(255) NOT NULL,`ipfs_hash` varchar(255) NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='geo對象模型';-- Indexes for table `geo_object`ALTER TABLE `geo_object`ADD PRIMARY KEY (`geo_id`),ADD SPATIAL KEY `geo_loc` (`geo_loc`);
複製代碼
有了以上的概念和設計模型,接下來,給你們看一個簡單的Demo實現:
IPFS單節點的部署就不詳細介紹了,這邊能夠參考文章 利用IPFS構建本身的去中心化分佈式Wiki系統 的實現過程.
官方提供了Curl的API方式,咱們能夠經過addIpfsDataByParam()方法實現RPC調用。
curl -F file=@myGeoFile "http://localhost:5001/api/v0/add?recursive=false&quiet=false&hash=sha2-256"
複製代碼
PS:這邊Demo採用的是本地單節點的數據上傳,爲了保障服務的穩定性,建議使用ipfs-cluster的節點集羣解決方案,具體方案能夠參考IPFS資深大牛(飛向將來)的文章《IPFS家族二》。
響應體爲 ‘multipart/form-data’格式,成功,會返回以下Body數據:
{"Name":"myGeoFile""Hash":"QmYftndCvcEiuSZRX7njywX2AGSeHY21Sa7VryCq1mK1Ew""Bytes":"2428803""Size": ""}
複製代碼
拿到Hash值後,再經過mixIpfsDataByParam()方法關聯到咱們的Geo位置數據上。
選取第一個基準位置點(模擬用戶所在定位):
維度lat:39.989049
經度lng:116.313658
複製代碼
INSERT INTO `geo_object`(`geo_loc`, `geo_address`, `ipfs_hash`) VALUES (GeomFromText('POINT(39.989049 116.313658)'),'3W咖啡館','QmYftndCvcEiuSZRX7njywX2A21Sa7VryCq1mK1Ew21')
複製代碼
選取第二個Geo位置點(模擬近點):
維度lat:39.988878
經度lng:116.313352
複製代碼
INSERT INTO `geo_object`(`geo_loc`, `geo_address`, `ipfs_hash`) VALUES (GeomFromText('POINT(39.988878 116.313352)'),'中關村創業大街南廣場','WCJIEFSCvcE231233HY21Sa7Vr1Cq1mK1Ew')
複製代碼
選取第三個Geo位置點(模擬遠點):
維度lat:40.005466
經度lng:116.315938
複製代碼
INSERT INTO `geo_object`(`geo_loc`, `geo_address`, `ipfs_hash`) VALUES (GeomFromText('POINT(40.005466 116.315938)'),'圓明園','KBYftndCvcEiuSZRX7njyw1332Y21Sa723mKASDED')
複製代碼
假設球面圍欄對角點座標A1(x1,y1),B1(x2,y2):
x1 = lat + distance / ( 111.1 / COS(RADIANS(lng))),
y1 = lng + distance / 111.1
x1 = lat - distance / ( 111.1 / COS(RADIANS(lng))),
y1 = lng - distance / 111.1
//構建一階空間填充曲線
LineString(A1,B1)
複製代碼
PS:
獲取1km之內的IPFS數據:
SELECT * FROM geo_object WHERE MBRContains
(
LineString
(
Point
( 39.989049 + 1 / ( 111.1 / COS(RADIANS(116.313658))), 116.313658 + 1 / 111.1 ),
Point
( 39.989049 - 1 / ( 111.1 / COS(RADIANS(116.313658))), 116.313658 - 1 / 111.1 )
),
geo_loc
)
複製代碼
以下圖所示,咱們拿到了距離3W咖啡館1Km之內中關村大街南廣場附近相關聯的IPFS數據:
獲取10km之內的IPFS數據:
SELECT * FROM geo_object WHERE MBRContains
(
LineString
(
Point
( 39.989049 + 10 / ( 111.1 / COS(RADIANS(116.313658))), 116.313658 + 10 / 111.1 ),
Point
( 39.989049 - 10 / ( 111.1 / COS(RADIANS(116.313658))), 116.313658 - 10 / 111.1 )
),
geo_loc
)
複製代碼
以下圖所示,咱們拿到了距離3W咖啡館10Km之內中關村大街南廣場附近相關聯的IPFS數據:
PS: 關於Demo這塊,後續會另外新開一篇實戰文章【應用】基於IPFS和GeoHash構建具備地理位置價值服務的DDApp(實戰篇)來作專門介紹,讓你們也能本身動手編寫一個功能相對完善(可視化界面)DDApp 。
初衷:指望能讓你們看到區塊鏈的實際應用場景,爲區塊鏈和傳統技術的結合作更多預演、佈道、分享,不去聽幣圈熙熙攘攘的聲音,用技術創造真實的價值,也期待更多和我同樣想法的朋友加入,帶一些正能量給這個圈子。
IPFS-Geo 意義:是一個具備地理位置特徵的IPFS智能對象,其元數據具有Geo相關特性,支持千萬級別空間數據的快速索引,對象內還提供LBS相關功能的接口服務。
圓方圓學院聚集大批區塊鏈名師,打造精品的區塊鏈技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。 公開課地址:ke.qq.com/course/3451…