Redis를 사용하여 대기열 생성에 중복된 항목이 없습니다.
(*webhook은 기본적으로 하나의 트리거.. 하나의 알림입니다. 즉, 저는 Shopify를 서버에 있는 URL로 설정하여 모든'제품 업데이트'나'주문 생성'등을 알려 줄 수 있습니다. http 호출의 주체는 제가 처리할 수 있는 JSON입니다.)
문제.
판매원이 제품을 갱신하는 방식은 때때로 대량 조작을 통해 이루어진다.즉, 여러 제품의 가격을 먼저 변경한 다음 같은 제품의 재고를 변경하는 등이다. 그들은 몇 분 안에 이 조작을 완성한다.이것은 같은 네트워크 갈고리에 대한 대량의 클릭을 초래할 것이다."많은 업데이트가 동일한 제품을 대상으로 하므로""중복""입니다."
또한 웹훅 내부에서는 초당 2개의 요청으로 제한되는 shopify API를 사용합니다.나의 웹훅스는 특히 대량 작업이 끝날 때 이 한계에 도달한다.그리고 재시도, 지수 회피 등이 필요하다.
전반적으로 말하자면, 이것은 나의 시스템이 중복된 작업을 많이 하고 엄격한 제한에 도달했다는 것을 의미한다.
솔루션
내가 구상한 해결 방안은 웹훅이 이 제품의 ID를 대기열에 추가하고 30분 간격으로 대기열에서 ID를 추출하여 유일한 ID를 찾은 후에 그것들을 한꺼번에 처리하는 것이다.
1-RabbitMQ 구현
자주 사용하는 대기 시스템 중 하나는 RabbitMQ입니다.그러나 RabbitMQ는 대기열의 메시지 중복을 잘 제거할 수 없습니다.
'예뻐요'가 무슨 뜻이에요?좋아요.대기열의 모든 정보를 읽고 코드를 통해 유일한 정보를 찾는 방법이 있다.즉, 데이터 중복 제거는 소비자가 수행합니다.가능하다면, 나는 차라리 대열에 중복된 것이 없기를 원한다.
그리고 난 이미 레드리스가 있어.만약 Redis를 사용할 수 있다면, 나는 유지보수가 필요한 다른 시스템을 추가하는 것을 피할 수 있다.
2-Redis 구현
Redis의 기능 목록에는 여러 데이터 구조가 있습니다.그것은 고정된 대열을 가지고 있다.하지만 이것은 RabbitMQ와 마찬가지로 내 코드는 메시지의 중복을 없애야 한다.Redis에는 또 다른 흥미로운 데이터 구조가 있는데 그것이 바로'정렬 집합'이다.
정렬 집합은 데이터 구조로 그 중에서 집합 중의 모든 항목에도 하나의 숫자 점수가 있기 때문에 점수의 정렬 순서에 따라 항목을 얻을 수 있다.
언뜻 보기에 이런 데이터 구조는 매우 직관적이지 않을 것이다.대기열은 목록일 뿐입니다.이해하기 쉽다.너는 물건을 밀어주고 튕길 수 있다.그러나 어떻게 정렬 집합을 대기열로 사용합니까?
직관성을 구축하기 위해서는 대기열의 모든 항목에 숫자가 연결되어 있어도 주의하십시오.만약 당신이 줄을 서 있는 열 번째 사람이라는 것을 알게 된다면, 그것은 당신 앞에 아홉 명이 있다는 것을 의미한다.다음 대열에 합류하는 사람은 11번째가 될 것이다.위치를 "득점"으로 간주하면 대기열의 새 항목의 득점 논리는 항상 대기열의 이전 항목 수 +1입니다.
그러나 정렬 세트에서 새 항목의 점수는 해당 항목의 위치에 따라 엄격하게 결정될 필요가 없다.그것은 어떠한 증가된 숫자도 될 수 있다.시간처럼.시간도 쉽게 얻을 수 있다.단, 같은 밀리초 안에 두 개의 항목을 추가하면 시간이 중복될 수 있습니다.그러나, 우리의 예에서, 이것은 문제가 아니다. 왜냐하면, 정렬집은 중복 점수를 허용하기 때문이다.삽입의 전체 순서를 심각하게 바꾸지 않는다면 중복된 점수는 거의 없을 것이다.우리가 더 관심을 가지는 것은 열쇠의 독특성이다.
그럼에도 불구하고, 나는 Redis 명령을 쓸 것이다. 이 명령은 정렬 집합에 키를 추가할 것이다. 이 키가 이 집합에 존재하지 않을 때만.
ZADD product-updates NX <currentTimeInMilliseconds> product-id-1
명령의 NX
은 중복 제품 ID가 대기열에 들어오는 것을 방지합니다.현재 소비자의 입장에서 나는 집합에 추가된 모든 가장 오래된 제품 ID를 얻을 수 있고 결과를 100으로 제한할 수 있다.집합에서 항목을 삭제하지 않았습니다.그냥 봤어요.ZRANGEBYSCORE product-updates 0 <currentTimeInMilliseconds> LIMIT 0 100
나는 모든 항목 (제품 id) 을 처리한 다음, 처리할 때 이 항목들을 하나씩 삭제하거나, 명령에서 100개의 항목을 삭제할 수 있다.ZREM product-updates product-id-1 product-id-2 ...
노동자와 부하의 균형
나에게 있어서 하나의 프로세스/라인은 이 일을 완성하기에 충분하다. 왜냐하면 내가 이 일을 병행화하려고 시도한다면, 나는shopify의 속도 제한에 도달할 수 있기 때문이다.그러나 다른 제한이 없는 용례에 대해서는 여러 명의 직원이 이 일을 완성하기를 원할 수도 있습니다.우리 어떻게 해야 돼요?
내 솔루션은 다음과 같은 가정을 바탕으로 합니다.
내가 사용하고자 하는 기교는 산열 함수를 사용하는 것이다.
hash("product-id") % numberOfQueues
해시 함수는 문자열을 받아들여 숫자를 되돌려줍니다.이것이 바로 여수 연산자%
의 작업 방식이다.같은 문자열에 대해서는 항상 같은 숫자를 되돌려줍니다.해시 함수의 출력은 반드시 매우 랜덤이어야만 믿을 수 있게 일할 수 있다.몇 개의 산열 함수가 있다.내가 가장 좋아하는 것은 fnv1a 이다. 왜냐하면 그것은 실현에 있어서 매우 작기 때문이다. (실제로는 10줄 코드)
예를 들자.만약 우리가 네 명의 노동자/대열을 가지고 있다면.
fnv1a("product-id-1") % 4 // = 0 always, if one uses https://www.npmjs.com/package/fnv1a
같은 제품 id를 전달하면 항상 같은 대기열 번호를 얻을 수 있습니다. 따라서, 생산 업체는 중복된 제품 id를 처리할 필요가 없고, 대기열 수가 변하지 않으면, 주어진 제품 id를 같은 대기열 번호에 일치하게 추가하려고 시도합니다.ZADD NX 명령은 대기열의 반복 항목을 처리합니다.(참고로 이런 방법은'점성 세션 부하 균형'이라고도 부른다)
본 서첩은 여기까지입니다.이 글은 중복된 항목이 포함되지 않은 상태에서 Redis를 사용하여 대기열을 실현하는 방법에 관한 것입니다.
Reference
이 문제에 관하여(Redis를 사용하여 대기열 생성에 중복된 항목이 없습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/munawwar/queues-with-redis-without-duplicate-items-4nlh텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)