[Redis] Geo

반응형

이번 글에서는 redis에서 geospatial data를 저장하는 방법인 geo에 대해 알아보겠습니다.

1. Geospatial이란?

geospatial 이란 지도상의 object들의 위치인 지리데이터를 의미합니다.

우리가 자주 사용하는 배달의 민족이나, 카카오 택시등의 서비스에서는 이러한 geospatial 데이터를 활용해 서비스를 제공합니다.

image.png

일반적으로 geospatial object를 저장하기 위해서는 longitude와 latitude의 pair를 저장합니다. 이러한 데이터의 저장은 다른 데이터 저장소에서도 가능하지만, redis를 사용하면 대규모 geospatial object 데이터의 저장 및 조회를 very low latency로 구현할 수 있습니다.

2. GeoHash

redis는 geospatial object의 데이터인 longitude와 latitude의 pair를 저장할때 실제로는 geohash 값을 저장합니다.

GeoHash는 52 bit integer 값을 가지며, geospatial object의 position을 최대 12 lenght의 string of letters와 digits으로 encode합니다. encode된 string은 location의 precison 값을 가집니다...

각각의 GeoHash는 key에 저장되며 이때 key의 data type은 sorted set입니다. sorted set 내부에 저장될때 각 GeoHash member는 score를 가지게됩니다.

😅 이해가 안되시죠?..

아래 그림으로 다시한번 설명해보겠습니다.

image.png

먼저 "Union Coffee"라는 카페가 있다고 가정하겠습니다. 이 카페의 경도와 위도를 -123/+12 라고 할 경우 이는 "Union Coffee"의 지리정보인 Geospatial data라고 할 수 있습니다. 이러한 데이터를 redis는 Geohash를 사용해 최대 12자리의 string인 "c2672gnx8p0"로 hash 합니다.

이제 이 hashed string은 Geopoints라는 key의 sorted set에 담겨지게 됩니다. Sorted set은 data를 저장할때 order의 기준을 정하기위해 score 값을 요구하기때문에, redis가 geohash 값을 확인해 score를 입력해줍니다.

결과적으로 geopoints라는 sorted set에는 "1558859838165330"의 score를 가진 "Union Coffee"라는 멤버가 담기게 되는 것 입니다. 이때 이 멤버의 실제 value는 hashed string인 "c2672gnx8p0"입니다.

이제 사용자는 hashed string인 "c2672gnx8p0"을 활용해 역으로 "Union Coffee"의 경도와 위도를 확인할 수 있습니다.

3. Command Line

자, 이번에는 command line에서 geohash를 사용해보겠습니다.

3-1) geoadd

먼저, geohash를 사용할 location의 longitude와 latitude가 필요합니다. https://www.google.com/maps 로 이동해 각자 원하는 위치의 longitude와 latitude를 확인합니다.

image.png

이제 redis-cli를 열어 아래와 같이 입력합니다. 제대로 입력했다면 결과값으로 1을 리턴합니다. 아래의 명령어를 통해 geopoints라는 sorted set에 "Union Coffee"의 geospatial data를 geohash한 값으로 저장했습니다.

image.png

zrange로 sorted set에 담겨있는 "Union Coffee" score를 확인해보면, redis가 값을 계산해두었습니다.

image.png

3-2) geohash

sorted set에 담겨있는 "Union Coffe"의 value 값(geoHash)을 확인하기위해선 아래의 명령어를 입력합니다.

image.png

위의 geohash 값은 "Union Coffee"의 geospatail data를 가지고 있음으로, http://geohash.org/ url의 맨뒤에 geohash값을 입력하면 지도에서 "Union Coffee"의 위치를 찾을 수 있습니다.

😎 url : geohash.org/wydq5dm2r00 <- url 맨뒤에다 geohash 값 입력

image.png

위에서 중요한점은 "wydq5dm2r00"인 geohash값은 precison 값을 가진다는 것 입니다.

즉, 만약 위의 string에서 일부를 제거한다면 해당 location의 정밀도가 떨어지게 됩니다. 예를 들어 뒤에 두자리수를 지워 "wydq5dm2r"로 검색해보면 아래와 같이 정밀도가 떨어진 location을 확인할 수 있습니다.

• 실제 위치 : 127.075390 / 37.629591
• "wydq5dm2r00" : 127.07538 / 37.62959
• "wydq5dm2r" : 127.0754 / 37.6296

image.png

3-3) geopops

위와 같은 값을 redis-cli에서 확인하기 위해선 아래의 명령어를 사용하면 됩니다.

image.png

3-4) geodist

이제 저장한 geohash값을 사용해 각 location 사이의 직선 거리를 측정해보도록 하겠습니다.

먼저 실습을 위한 2곳의 location을 geopoints에 추가합니다. 저는 "CU"와 "seoultech"이라는 location을 geopoints에 추가했습니다.

image.png

다음으로 "CU"와 "seoultech"사이의 직선 거리를 확인하고 싶으면 아래의 명령어를 입력하면 됩니다.

image.png

반환 거리의 단위도 아래와 같이 변경할 수 있습니다. [m,mi,km]

image.png

3-5) georadiusbymember

georadiusbymember 명령어를 사용하면, 특정 member의 radius 범위 내에 있는 member들을 손쉽게 찾을 수 있습니다.

image.png

명령어는 아래와 같습니다. 저는 CU의 100m radius 내에 있는 모든 member를 찾아보았습니다. 여기서 withdist는 거리를 / withcoord는 위도와 경도를 / withhash는 hashcore를 리턴합니다.

image.png

georadiusbymember 명령어를 사용하면 해당 위치에서 가장 먼곳에 위치한 member나 가장 가까운곳에 member도 찾을 수 있습니다 😁.

아래와 같이 입력하면 가장 먼곳의 member를 찾을 수 있습니다. 해석하자면, CU의 100m radius 이내의 member를 찾고 이를 거리가 먼순부터 정렬한뒤 1개의 member만 리턴하는 것입니다.

image.png

가장 가까운 지점을 찾기 위해서는 Count에는 2를 입력해야합니다. 기본적으로 가장 가까운 거리는 자기자신으로 리턴되기 때문입니다.

image.png

만약 위에서 찾은 member들을 또다른 sorted set에 저장하기 위해서는 아래와 같이 입력합니다. 이때는 withdist/withcoord는/withhash 변수는 사용할 수 없습니다. 또한, 저장된 member들의 score는 각 member들의 hash 값입니다.

image.png

만약 member의 score를 hash가 아닌 dist로 저장하고 싶은 경우에는 아래와 같이 입력하면 됩니다.

image.png


참고 자료 : https://www.udemy.com/course/redis-bootcamp-for-beginners/


추천서적

 

Redis Essentials

COUPANG

www.coupang.com

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음


반응형

'Redis' 카테고리의 다른 글

[Redis] CRUD with Spring Boot -1  (0) 2020.08.21
[Redis] HyperLogLog  (0) 2020.08.21
[Redis] Publish/Subscribe  (0) 2020.08.20
[Redis] Transaction  (0) 2020.08.20
[Redis] Sorted Set  (0) 2020.08.20

댓글

Designed by JB FACTORY