Redis 의 GeoHash 상세 설명

8503 단어 RedisGeoHash
Redis 는 3.2 버 전 이후 지리 적 위치 GEO 모듈 을 추 가 했 는데 이것 은 우리 가 Redis 를 사용 하여 모 바 이 자전거'근처 의 Mobike',미 단 과 배 고 프 세 요?'근처 의 식당'이라는 기능 을 실현 할 수 있다 는 것 을 의미한다.
데이터베이스 로 부근의 사람 을 계산 하 다
지도 요소 의 위치 데 이 터 는 2 차원 의 경 위 를 사용 하여 경도 범위(-180,180),위도 범위(-90,90),위도 정 부 는 적 도 를 경계 로 하고 북 정 남 부 는 마이너스 이 며 경도 정 부 는 본 초 자오선(영국 그리니치 천문대)을 경계 로 하고 동 정서 음 을 나타 낸다.예 를 들 어 금 을 파 는 사무실 은 왕 징 SOHO 에 있 는데 그의 경위도 좌 표 는(116.48105,39.996794)이 고 모두 정수 이다.왜냐하면 중국 은 동북 반구 에 있 기 때문이다.
두 원소 의 거리 가 그리 멀 지 않 을 때,바로 피타 고 라 스 정 리 를 사용 하면 원소 간 의 거 리 를 계산 할 수 있다.우리 가 평소에 사용 하 는'부근의 사람'의 기능 은 요소 의 거리 가 그리 크 지 않 고 피타 고 라 스 정리 가 충분 하 다 고 할 수 있다.그러나 주의해 야 할 것 은 경위도 좌표 의 밀도 가 다르다 는 것 이다.
지금 만약 에'부근의 사람'을 계산 하려 면 원소 의 좌 표를 정 한 다음 에 이 좌표 부근의 다른 원 소 를 계산 하고 거리 에 따라 정렬 을 하려 면 어떻게 손 을 써 야 합 니까?
在这里插入图片描述
현재 요소 의 위도 좌표 가 관계 데이터베이스(요소 id,경도 x,위도 y)를 사용 하여 저장 된다 면 어떻게 계산 해 야 합 니까?
우선,당신 은 모든 요소 와 목표 요소 의 거 리 를 여러 번 계산 한 후에 정렬 할 수 없습니다.이 계 산 량 이 너무 많아 서 성능 기준 이 만족 할 수 없 을 것 입 니 다.일반적인 방법 은 직사각형 구역 을 통 해 원소 의 수량 을 제한 한 다음 에 구역 내의 원 소 를 전량 거리 로 계산 하여 정렬 하 는 것 이다.이렇게 하면 계 산 량 을 뚜렷하게 줄 일 수 있다.어떻게 사각형 구역 을 구분 합 니까?반경 r 를 지정 할 수 있 습 니 다.SQL 을 사용 하면 원 을 그 릴 수 있 습 니 다.사용자 가 걸 러 낸 결과 에 만족 하지 않 으 면 반경 을 확대 하여 계속 선별 하 세 요.

select id from positions where x0-r < x < x0+r and y0-r < y < y0+r
고성능 의 사각형 영역 알고리즘 을 만족 시 키 기 위해 데이터 시트 는 경위도 좌표 에 양 방향 복합 색인(x,y)을 더 해 야 조회 성능 을 최대 화 할 수 있다.
그러나 데이터 베 이 스 를 조회 하 는 성능 이 유한 하기 때문에 만약 에'근처에 있 는 사람'의 조회 요청 이 매우 많 으 면 높 은 병행 장소 에서 이것 은 좋 은 방안 이 아 닐 수 있 습 니 다.
GeoHash 알고리즘
업계 에서 비교적 통용 되 는 지리 적 위치 거리 정렬 알고리즘 은 GeoHash 알고리즘 이 고 Redis 도 GeoHash 알고리즘 을 사용한다.GeoHash 알고리즘 은 2 차원 의 경위도 데 이 터 를 1 차원 의 정수 에 비 추어 모든 요소 가 한 라인 에 마 운 트 되 고 가 까 운 2 차원 좌표 가 1 차원 뒤의 점 사이 의 거리 도 가 까 워 집 니 다.우리 가'근처에 있 는 사람'을 계산 하려 면 먼저 목표 위 치 를 이 라인 에 투사 한 다음 에 이 1 차원 라인 에서 근처 의 점 을 얻 으 면 된다.
그럼 이 매 핑 알고리즘 은 구체 적 으로 어떤 것 입 니까?그것 은 지 구 를 2 차원 평면 으로 보고 일련의 정사각형 격자 로 나 누 었 는데 마치 바둑 판 과 같다.모든 지도 요소 좌 표 는 유일한 격자 에 놓 여 있 습 니 다.격자 가 작 을 수록 좌 표 는 정확 하 다.그리고 이 격자 들 을 정수 인 코딩 하면 가 까 운 격자 인 코딩 일수 록 가 까 워 집 니 다.그럼 인 코딩 은 어떻게 하나 요?가장 간단 한 방안 은 케이크 를 자 르 는 방법 이다.정사각형 케이크 를 네 앞 에 놓 고 두 칼 을 내 려 가면 모두 네 개의 작은 정사각형 으로 나 눌 수 있다.이 네 개의 작은 정사각형 은 각각 00,01,10,11 개의 이 진 정수 로 표시 할 수 있다.그 다음 에 모든 작은 정사각형 에 대해 이 도 법 으로 계속 자 르 면 작은 정사각형 마다 4bit 의 이 진 정 수 를 사용 하여 표시 할 수 있다.그리고 계속 자 르 면 정사각형 이 점점 작 아 지고 이 진 정수 도 점점 길 어 지고 정확도 도 점점 높아진다.
위의 예 에서 사용 한 것 은 이 도 법 이 고 실제 알고리즘 에는 다른 도 법 이 많 으 며 최종 적 으로 인 코딩 된 정수 숫자 도 모두 다르다.
인 코딩 을 한 후에 모든 지도 요소 의 좌 표 는 하나의 정수 가 될 것 이다.이 정 수 를 통 해 요소 의 좌 표를 복원 할 수 있 고 정수 가 길 수록 복 원 된 좌표 값 의 손실 정도 가 적다.'부근의 사람'이라는 기능 에 있어 손실의 정확 도 는 무시 할 수 있다.
GeoHash 알고리즘 은 이 정수 에 대해 base 32 인 코딩(0-9,a-z 에서 a,i,l,o 네 자 모 를 제거)을 계속 문자열 로 바 꿉 니 다.Redis 에서 경 위 는 52 비트 의 정 수 를 사용 하여 인 코딩 을 하고 zset 에 넣 었 습 니 다.zset 의 value 는 요소 의 key 이 고 score 는 GeoHash 의 52 비트 정수 입 니 다.zset 의 score 는 부동 소수점 이지 만 52 비트 의 전체 수 치 는 무 손실 저장 할 수 있 습 니 다.
Redis 를 사용 하여 Geo 조 회 를 진행 할 때,우 리 는 항상 그것 의 내부 구 조 는 사실상 zset(skiplist)일 뿐 이 라 고 생각해 야 한다.zset 의 score 정렬 을 통 해 좌표 근처 의 다른 요 소 를 얻 을 수 있 습 니 다.(실제 상황 은 복잡 하지만 충분히 이해 합 니 다)score 를 좌표 값 으로 복원 하면 요소 의 원시 좌 표를 얻 을 수 있 습 니 다.
Redis 의 Geo 명령 어 기본 사용
레 디 스 가 제공 하 는 지 오 지령 은 6 개 에 불과 해 독자 들 이 순식간에 파악 할 수 있다.사용 할 때 독자 들 은 반드시 다시 생각해 야 한다.그것 은 단지 일반적인 zset 구조 일 뿐이다.
증가시키다
geoadd 명령 은 집합 이름과 여러 개의 위도 이름 3 원 그룹 을 가지 고 있 습 니 다.여 기 는 여러 개의 3 원 그룹 을 추가 할 수 있 습 니 다.

127.0.0.1:6379> geoadd company 116.48105 39.996794 juejin
(integer) 1
127.0.0.1:6379> geoadd company 116.514203 39.905409 ireader
(integer) 1
127.0.0.1:6379> geoadd company 116.489033 40.007669 meituan
(integer) 1
127.0.0.1:6379> geoadd company 116.562108 39.787602 jd 116.334255 40.027400 xiaomi
(integer) 2
거리.
geodist 명령 은 두 요소 간 의 거 리 를 계산 하고 집합 명칭,두 개의 명칭 과 거리 단 위 를 휴대 할 수 있다.

127.0.0.1:6379> geodist company juejin ireader km
"10.5501"
127.0.0.1:6379> geodist company juejin meituan km
"1.3878"
127.0.0.1:6379> geodist company juejin jd km
"24.2739"
127.0.0.1:6379> geodist company juejin xiaomi km
"12.9606"
127.0.0.1:6379> geodist company juejin juejin km
"0.0000"
우 리 는 금 을 파 는 것 이 미 단 에서 가장 가 까 운 것 을 볼 수 있다.왜냐하면 그들 은 모두 베 이 징 을 바라 보고 있 기 때문이다.거리 단 위 는 m,km,ml,ft 로 각각 미터,킬로미터,마일 과 척 을 대표 할 수 있다.
원소 위치 가 져 오기
geopos 명령 은 집합 에 있 는 임의의 요소 의 경위도 좌 표를 얻 을 수 있 고 한 번 에 여러 개 를 얻 을 수 있 습 니 다.

127.0.0.1:6379> geopos company juejin
1) 1) "116.48104995489120483"
 2) "39.99679348858259686"
127.0.0.1:6379> geopos company ireader
1) 1) "116.5142020583152771"
 2) "39.90540918662494363"
127.0.0.1:6379> geopos company juejin ireader
1) 1) "116.48104995489120483"
 2) "39.99679348858259686"
2) 1) "116.5142020583152771"
 2) "39.90540918662494363"
우 리 는 얻 은 경위도 좌표 와 geoadd 가 들 어간 좌표 에 경미 한 오차 가 있 는 것 을 관찰 했다.그 이 유 는 geohash 가 2 차원 좌 표를 1 차원 으로 매 핑 하 는 것 이 손 상 된 것 이 고 매 핑 을 통 해 다시 복원 하 는 값 은 비교적 작은 차이 가 나타 날 수 있 기 때문이다.'부근의 사람'이라는 기능 에 있어 서 이 정도 의 오 차 는 전혀 문제 가 아니다.
요소 의 hash 값 가 져 오기
geohash 는 요소 의 경위도 인 코딩 문자열 을 가 져 올 수 있 습 니 다.위 에서 언급 한 것 은 base 32 인 코딩 입 니 다.너 는 이 인 코딩 값 을 사용 할 수 있다http://geohash.org/${hash}에서 직접 위 치 를 지정 합 니 다.geohash 의 표준 인 코딩 값 입 니 다.

127.0.0.1:6379> geohash company ireader
1) "wx4g52e1ce0"
127.0.0.1:6379> geohash company juejin
1) "wx4gd94yjn0"
주소 좀 열 어 달 래 요.http://geohash.org/wx4g52e1ce0지도 가 가리 키 는 위치 가 정확 한 지 살 펴 보 자.
在这里插入图片描述
좋아,바로 이 자리 야,아주 정확 해.
근처 회사
georadius by member 명령 은 가장 관건 적 인 명령 입 니 다.지정 한 요소 근처 의 다른 원 을 조회 할 수 있 습 니 다.
소,그것 의 매개 변 수 는 매우 복잡 하 다.

#    20        3         ,       
127.0.0.1:6379> georadiusbymember company ireader 20 km count 3 asc
1) "ireader"
2) "juejin"
3) "meituan"
#    20        3         
127.0.0.1:6379> georadiusbymember company ireader 20 km count 3 desc
1) "jd"
2) "meituan"
3) "juejin"
#        withcoord withdist withhash         
# withdist    ,         
127.0.0.1:6379> georadiusbymember company ireader 20 km withcoord withdist withhash count 3 asc
1) 1) "ireader"
 2) "0.0000"
 3) (integer) 4069886008361398
 4) 1) "116.5142020583152771"
 2) "39.90540918662494363"
2) 1) "juejin"
 2) "10.5501"
 3) (integer) 4069887154388167
 4) 1) "116.48104995489120483"
 2) "39.99679348858259686"
3) 1) "meituan"
 2) "11.5748"
 3) (integer) 4069887179083478
 4) 1) "116.48903220891952515"
 2) "40.00766997707732031"
georadius by member 명령 은 요소 에 따라 근처 의 요 소 를 조회 하 는 것 을 제외 하고 Redis 는 좌표 값 에 따라 근처 의 요 소 를 조회 하 는 것 도 제공 합 니 다.이 명령 은 사용자 의 위치 에 따라'근처 의 차','근처 의 식당'등 을 계산 할 수 있 습 니 다.목표 요 소 를 경위도 좌표 값 으로 바 꾸 는 것 을 제외 하고 georadius by member 와 거의 일치 합 니 다.

127.0.0.1:6379> georadius company 116.514202 39.905409 20 km withdist count 3 asc
1) 1) "ireader"
 2) "0.0000"
2) 1) "juejin"
 2) "10.5501"
3) 1) "meituan"
 2) "11.5748"
소결&주의사항
한 지도 응용 에서 차 의 데이터,식당 의 데이터,사람의 데 이 터 는 백만 천만 개가 될 수 있 습 니 다.만약 에 Redis 의 Geo 데이터 구 조 를 사용 하면 모두 zset 집합 에 넣 을 것 입 니 다.Redis 의 클 러 스 터 환경 에서 집합 은 한 노드 에서 다른 노드 로 이전 할 수 있 습 니 다.만약 에 하나의 key 의 데이터 가 너무 크 면 클 러 스 터 의 이전 작업 에 큰 영향 을 줄 수 있 습 니 다.클 러 스 터 환경 에서 하나의 key 에 대응 하 는 데이터 양 이 1M 를 초과 해 서 는 안 됩 니 다.그렇지 않 으 면 클 러 스 터 이전 에 카드 현상 이 나타 나 온라인 서비스의 정상 적 인 운행 에 영향 을 줄 수 있 습 니 다.
따라서 Geo 의 데 이 터 는 단독 Redis 인 스 턴 스 배 치 를 사용 하고 클 러 스 터 환경 을 사용 하지 않 는 것 을 권장 합 니 다.
만약 에 데이터 의 양 이 억 이 넘 고 심지어 더 많 으 면 Geo 데 이 터 를 나 누 어야 한다.국가 에 따라 나 누고 성 에 따라 나 누 며 시 에 따라 나 누 어야 한다.인구 가 큰 도시 에 서 는 심지어 지역 에 따라 나 눌 수 있다.이렇게 하면 하나의 zset 집합 크기 를 현저히 낮 출 수 있다.
레 디 스 의 지 오 하 쉬 에 대한 자세 한 설명 은 여기까지 입 니 다.레 디 스 의 지 오 하 쉬 에 관 한 더 많은 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기