golang地理定位数据库与实时地理围栏插件库Tile38的使用
Golang地理定位数据库与实时地理围栏插件库Tile38的使用
Tile38是一个开源(MIT许可)的内存地理定位数据存储、空间索引和实时地理围栏服务器。它支持多种对象类型,包括经纬度点、边界框、XYZ瓦片、Geohash和GeoJSON。
主要特性
- 支持Nearby、Within和Intersects等搜索方法的空间索引
- 通过webhooks或pub/sub通道实现实时地理围栏
- 支持多种对象类型:经纬度点、边界框、Geohash、GeoJSON、QuadKey和XYZ瓦片
- 支持多种协议:HTTP(使用curl)、WebSockets、Telnet和Redis RESP协议
- 服务器响应格式为RESP或JSON
- 完整的命令行界面
- 主从复制
- 内存数据库支持持久化到磁盘
安装Tile38
Docker方式
docker pull tile38/tile38
docker run -p 9851:9851 tile38/tile38
Homebrew(macOS)
brew install tile38
tile38-server
Golang客户端示例
以下是使用Go语言操作Tile38的完整示例代码:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/xjem/t38c"
)
func main() {
// 创建Tile38客户端
client, err := t38c.New("localhost:9851", t38c.Debug)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// 设置一个点对象
err = client.Keys.Set("fleet", "truck1").Point(33.5123, -112.2693).Do()
if err != nil {
log.Fatal(err)
}
// 设置带有字段的点对象
err = client.Keys.Set("fleet", "truck2").
Point(33.4626, -112.1695).
Field("speed", 90).
Field("age", 21).
Do()
if err != nil {
log.Fatal(err)
}
// 搜索附近的对象
searchRes, err := client.Search.Nearby("fleet", 33.462, -112.268, 6000).Do()
if err != nil {
log.Fatal(err)
}
fmt.Printf("附近6公里内的对象: %+v\n", searchRes)
// 创建地理围栏
fenceChan := make(chan t38c.GeofenceEvent)
go func() {
err := client.Geofence.Nearby("fleet", 33.462, -112.268, 6000).
Actions(t38c.Enter, t38c.Exit).
Do(fenceChan)
if err != nil {
log.Fatal(err)
}
}()
// 监听地理围栏事件
go func() {
for event := range fenceChan {
fmt.Printf("地理围栏事件: %+v\n", event)
}
}()
// 更新对象位置以触发地理围栏
time.Sleep(1 * time.Second)
err = client.Keys.Set("fleet", "truck1").Point(33.462, -112.268).Do()
if err != nil {
log.Fatal(err)
}
// 等待一段时间查看结果
time.Sleep(5 * time.Second)
}
基本操作示例
添加和查询对象
// 添加点对象
err := client.Keys.Set("fleet", "truck1").Point(33.5123, -112.2693).Do()
// 查询对象
getRes, err := client.Keys.Get("fleet", "truck1").Do()
// 扫描集合中的所有对象
scanRes, err := client.Search.Scan("fleet").Do()
地理围栏
// 创建地理围栏通道
fenceChan := make(chan t38c.GeofenceEvent)
// 设置地理围栏
err := client.Geofence.Within("fleet").
Polygon([][2]float64{{0, 0}, {10, 10}, {10, 0}, {0, 0}}).
Actions(t38c.Enter, t38c.Exit, t38c.Cross).
Do(fenceChan)
// 监听围栏事件
go func() {
for event := range fenceChan {
switch event.Detect {
case "enter":
fmt.Printf("对象 %s 进入区域\n", event.ID)
case "exit":
fmt.Printf("对象 %s 离开区域\n", event.ID)
case "cross":
fmt.Printf("对象 %s 穿过区域\n", event.ID)
}
}
}()
使用字段
// 设置带有字段的对象
err := client.Keys.Set("fleet", "truck1").
Point(33.5123, -112.2693).
Field("speed", 90).
Field("age", 21).
Do()
// 获取字段值
fgetRes, err := client.Keys.FGet("fleet", "truck1", "speed").Do()
// 使用WHERE条件搜索
searchRes, err := client.Search.Nearby("fleet", 33.462, -112.268, 6000).
Where("speed", 70, "+inf").
Do()
对象类型支持
Tile38支持多种地理对象类型:
经纬度点
// 基本点
client.Keys.Set("fleet", "truck1").Point(33.5123, -112.2693).Do()
// 带高程的点
client.Keys.Set("fleet", "truck1").PointZ(33.5123, -112.2693, 225).Do()
边界框
client.Keys.Set("fleet", "truck1").Bounds(30, -110, 40, -100).Do()
GeoJSON
geojson := `{
"type": "Polygon",
"coordinates": [[[0,0],[10,10],[10,0],[0,0]]]
}`
client.Keys.Set("city", "tempe").Object(geojson).Do()
高级功能
搜索选项
// 使用WHERE和LIMIT
searchRes, err := client.Search.Within("fleet").
Circle(33.462, -112.268, 6000).
Where("speed", 70, "+inf").
Where("age", "-inf", 24).
Match("truck*").
NoFields().
Limit(10).
Do()
发布/订阅通道
// 创建通道
err := client.Channels.Set("busstop").
Nearby("buses").
Point(33.5123, -112.2693, 200).
Do()
// 订阅通道
subChan := make(chan t38c.PubSubMessage)
err := client.PubSub.Subscribe("busstop", subChan)
// 监听消息
go func() {
for msg := range subChan {
fmt.Printf("收到消息: %+v\n", msg)
}
}()
性能监控
Tile38支持Prometheus指标:
# 启动服务器并启用Prometheus指标
./tile38-server --metrics-addr=127.0.0.1:4321
# 访问指标
curl http://127.0.0.1:4321/metrics
以上示例展示了如何在Golang中使用Tile38进行地理定位数据存储和实时地理围栏监控。Tile38提供了丰富的功能和灵活的API,非常适合构建需要实时地理位置服务的应用程序。
更多关于golang地理定位数据库与实时地理围栏插件库Tile38的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang地理定位数据库与实时地理围栏插件库Tile38的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang地理定位数据库与Tile38实时地理围栏使用指南
Tile38是一个高性能的地理定位数据库和实时地理围栏引擎,支持多种地理空间数据类型和查询操作。下面我将介绍如何在Golang中使用Tile38。
Tile38简介
Tile38主要特性:
- 支持点、线、多边形、边界框等地理空间数据类型
- 提供实时地理围栏功能
- 支持多种查询:附近搜索、范围内搜索、交叉搜索等
- 提供HTTP、WebSocket和RESP(Redis协议)接口
安装Tile38客户端库
go get github.com/tidwall/tile38-client
基本使用示例
1. 连接Tile38服务器
package main
import (
"fmt"
"github.com/tidwall/tile38-client"
)
func main() {
// 连接Tile38服务器,默认端口9851
client, err := tile38.New("localhost:9851")
if err != nil {
panic(err)
}
defer client.Close()
// 测试连接
pong, err := client.Ping()
if err != nil {
panic(err)
}
fmt.Println("Ping response:", pong)
}
2. 存储和查询位置数据
// 存储一个点
func setLocation(client *tile38.Client) error {
// 设置一个名为"fleet"的集合中的对象"truck1"的位置
err := client.Set("fleet", "truck1").Point(33.5123, -112.2693).Do()
if err != nil {
return err
}
fmt.Println("Location set successfully")
return nil
}
// 查询附近的对象
func nearbySearch(client *tile38.Client) error {
// 查询距离(33.462, -112.268) 5000米范围内的对象
objects, err := client.Nearby("fleet").
Distance().
Point(33.462, -112.268, 5000).
Do()
if err != nil {
return err
}
fmt.Println("Nearby objects:")
for _, obj := range objects {
fmt.Printf("ID: %s, Distance: %.2fm, Point: %v\n",
obj.ID, obj.Distance, obj.Point)
}
return nil
}
3. 实时地理围栏
// 设置地理围栏
func setupGeofence(client *tile38.Client) error {
// 创建一个WebSocket连接来接收围栏通知
ws, err := client.Geofence("fence1").
Within("fleet").
Circle(33.462, -112.268, 1000).
Actions(tile38.Enter, tile38.Exit).
Do()
if err != nil {
return err
}
// 处理围栏事件
go func() {
for {
msg, err := ws.Receive()
if err != nil {
fmt.Println("Geofence error:", err)
return
}
switch msg.Detect {
case tile38.Enter:
fmt.Printf("Object %s entered the area at %v\n", msg.ID, msg.Time)
case tile38.Exit:
fmt.Printf("Object %s exited the area at %v\n", msg.ID, msg.Time)
}
}
}()
return nil
}
4. 多边形围栏和复杂查询
// 使用多边形设置地理围栏
func polygonGeofence(client *tile38.Client) error {
// 定义多边形顶点
polygon := [][2]float64{
{33.462, -112.268},
{33.471, -112.269},
{33.470, -112.259},
{33.462, -112.258},
}
// 设置多边形围栏
err := client.Set("areas", "warehouse").Polygon(polygon).Do()
if err != nil {
return err
}
// 查询在仓库多边形内的车辆
objects, err := client.Intersects("fleet").
Get("areas", "warehouse").
Do()
if err != nil {
return err
}
fmt.Println("Vehicles in warehouse area:")
for _, obj := range objects {
fmt.Printf("ID: %s, Point: %v\n", obj.ID, obj.Point)
}
return nil
}
高级功能
1. 使用通道(CHAN)进行发布/订阅
func setupChannel(client *tile38.Client) error {
// 订阅通道
ws, err := client.Subscribe("alerts")
if err != nil {
return err
}
go func() {
for {
msg, err := ws.Receive()
if err != nil {
fmt.Println("Channel error:", err)
return
}
fmt.Printf("Received alert: %s\n", msg.Message)
}
}()
// 向通道发布消息
err = client.Publish("alerts", "Truck1 speed exceeded limit")
if err != nil {
return err
}
return nil
}
2. 使用Hook实现事件触发
func setupHook(client *tile38.Client) error {
// 设置一个HTTP Hook,当有车辆进入围栏时触发
err := client.SetHook("speed-alert", "http://your-server/alerts").
Nearby("fleet").
Point(33.462, -112.268, 1000).
Do()
if err != nil {
return err
}
fmt.Println("Hook set up successfully")
return nil
}
性能优化建议
- 使用连接池管理Tile38连接
- 对于大量数据插入,考虑使用Pipeline
- 合理设置围栏检测精度(使用DETECT参数)
- 对频繁查询的数据建立索引
总结
Tile38为Golang开发者提供了强大的地理空间数据处理能力,特别适合需要实时地理围栏功能的应用程序。通过上述示例,您可以快速上手Tile38的基本功能,并根据项目需求扩展更复杂的地理空间应用。
要了解更多细节,可以参考Tile38官方文档:https://tile38.com/