Redis 의 GeoHash 상세 설명
데이터베이스 로 부근의 사람 을 계산 하 다
지도 요소 의 위치 데 이 터 는 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 집합 크기 를 현저히 낮 출 수 있다.
레 디 스 의 지 오 하 쉬 에 대한 자세 한 설명 은 여기까지 입 니 다.레 디 스 의 지 오 하 쉬 에 관 한 더 많은 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
그래프 구조를 무상으로 취급할 수 없는 것은 싫기 때문에, redisgraph를 WSL2에 극치고 설치해 보았습니다.제목은 만우절이므로. 그렇다, 역시, 앞으로는 그래프 구조 데이터베이스라고 생각했다. 생각한 것은 몇 년 전인가. 전부터 Neo4j는 시험하고 있지만, 영업 분들로부터 상용 라이센스가 높다고 가르쳐 주었으므로, 전전...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.