【redis存储结构设计】存储坐标点及其多维度点击数
伊谢尔伦
伊谢尔伦 2017-04-22 08:59:44
0
2
851

我现在有个需求

需要记录页面点击数据,上游吐到redis中,

上游怎么吐到redis中对我们来说是透明的,

我们只用关心redis中如何存储就好。


查询需求:

  1. 查询某天某页面下所有点击数,即有效点击总数+无效点击总数

  2. 查询某天某页面某分辨率下 所有有效点击总数无效点击总数

  3. 查询某天某页面某分辨率下所有的坐标点及点击数

  4. 框选查询(相当于范围查询) 查询某天某页面某分辨率下 某个范围(比如100<x<1000,30<y<600)坐标点的有效点击总数无效点击总数
    同时还有各种维度的有效点击数和无效点击数

需求解释:

关于有效点击和无效点击:我们进行存储时可以用0和1区分,至于前端如何定义有效或者无效,对我们透明。

关于分辨率:按宽度区分共有三种:比如1380 1190 1000; 根据现有实现:有了分辨率可以将zset切割的小一些,比如没有分辨率可能有共10w个key 的zset,有了分辨率我一次最多查询某个分辨率下 可能只有3w个key 的zset

关于框选: 就是用鼠标在页面上从左上到右下划出一个框, 我们会查询这个选择框范围(如100<x<1000,30<y<600)内所有的点相关的数据。

关于维度: 就是点击这个点的用户 所在地区所使用浏览器

当前实现

上游吐过来的点经过处理存入redis,
x,y都经过

Math.ceil(realx / 4.0) * 4;
Math.ceil(realy / 4.0) * 4;

处理,即相当于4个点为一个点存储到redis.

使用4个zset来实现需求。

一个 zset 记录某天某页面某分辨率的数据
key 为 date_pageid_分辨率 member为: 有效OR无效_ 浏览器_ 地区
score 为点击数
举例key : 20140908_0001_1000
member: 0_1_1 0对应无效点击,1对应浏览器表中的QQ浏览器,1对应地区表中的上海
score:10


每个坐标点相关数据都用一个对应的zset记录
key为 date_pageid_分辨率_ 横坐标_ 纵坐标
member为: 有效OR无效浏览器地区
score为点击数
举例key : 20140908_0001_1000_23_478
member: 0_1_2 0对应无效点击,1对应浏览器表中的QQ浏览器,2对应地区表中的北京
score:12
这样可以理解为,坐标为(23,478)这个点,在20140908这一天,pageid为0001的页面上,
分辨率为1000的时候,来自北京地区的,使用QQ浏览器,进行的无效点击数为12


两个zset 做辅助范围查询

通过zrangebyscore 分别获得x,y范围(如100<x<1000,30<y<600)对应的key集

然后取交集获得需要查询的真正key集

y的辅助查询zet
key为: date_pageid_分辨率y eg.20140908_0001_1000_y
member: 为 ​date_pageid
分辨率_ 横坐标 _纵坐标 eg.20140908_0001_1000_23_478
score为:横坐标y的值​ eg.478

x的辅助查询zet
key为: date_pageid_分辨率x eg.20140908_0001_1000_x
member: 为 ​date_pageid
分辨率_ 横坐标 _纵坐标 eg.20140908_0001_1000_23_478
score为:横坐标X的值​ eg.23


当前实现存在的问题

查询速度太慢

举例比如我想一次取出某天某页面某分辨率下所有的点
可能需要一次查询几万个key eg. keys("20140908_0001_1000_*");
获得查询的key集之后 ,还需要使用zrange(key) 得到每个key下的member集,然后再使用
zscore(key,member) 获得对应的key和 member下的score值

可以看到这个操作: 串行化执行,不容易改成并行化。

暂时的解决方案:可以利用异步任务执行 ,进行缓存以优化查询速度,但是有可能引起redis慢查询问题。


框选行为
举例:查询范围(如100<x<1000,30<y<600)

使用zrangeByScore(key, 100, 1000)``zrangeByScore(key, 30, 600)

查出x,y在各自范围分别对应的key集,然后取交集 获得最终需要查询的key集

获得查询的key集之后 ,还需要使用zrange(key) 得到每个key下的member集,

然后再使用zscore(key,member) 获得对应的key和 member下的score值

缺点:因为查询范围不定,所以无法进行缓存,当查询范围很大时,即key很多的时候,查询速度很慢。和上面查询坐标点一样串行化执行,不容易改成并行化。有可能引起redis慢查询问题。


不知道大家针对我现在的实现方案有什么更好的优化策略
或者针对查询需求有没有什么更好的设计方案
新人第一次发帖,感谢@暗雨西喧对排版的提醒。
请大家多指教。

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

모든 응답(2)
PHPzhong

즉, 키가 많으면 쿼리 속도가 매우 느려집니다

많은 키를 사용하여 쿼리하면 속도가 느려집니다. 이는 마지막 쿼리에서 실제로 클릭한 zset을 의미합니까?

결의안이 몇 개나 있을지 모르겠어요? zset의 키를 수정하여 해상도를 갖지 않고 값에 해상도를 갖도록 수정할 수 있습니다. 이렇게 하면 검색 조건에 해상도가 있는 경우 값을 검색한 후 일부 필터링을 수행할 수 있으며 속도가 매우 빨라집니다. 빠른.

하지만 상자 선택 동작은 범위가 가변적이기 때문입니다
프레임 선택 쿼리 (범위 쿼리와 동일) 특정 날짜, 특정 페이지, 특정 해상도에 대한 쿼리
특정 범위(예: 100

사용자에게 검색할 영역을 수동으로 그려달라고 요청하는 것과 같습니다. 전체 이미지를 포함하도록 이 조건을 변경하는 것을 고려해 볼 수 있나요? 10개 부분(100개 부분, 10,000개 부분)으로 잘라냅니다. 조건은 단순히 무작위로 그리는 것이 아니라 특정 사각형만 선택할 수 있습니다. 이러한 방식으로 각 사각형의 데이터를 예측 가능하게 "요약"할 수 있습니다. .

먼저 이에 대해 이야기하고 도움이 되는지 살펴보겠습니다. 그래도 최적화가 필요한 경우 질문에 있는 쿼리 설명을 수정하면 보완할 수 있는 부분이 있지만, 도움이 되실지 모르겠습니다. 이것을 표현하고 싶어서 간단한 예를 들어보겠습니다. 그리고 조판을 사용해 보세요. 매우 피곤할 것 같습니다


질문을 수정하신 후 답변을 따로 작성했습니다

우선 scop에 따라 자동으로 인덱스를 정렬하는 zset의 본질을 사용하고 있지 않다는 점을 말씀드립니다. 예

zset은 특정 날짜의 특정 페이지와 특정 해상도의 데이터를 기록합니다
키는 date_pageid_solution이고 멤버는 다음과 같습니다: valid OR valid_browser_region
점수는 클릭수입니다
예: 키 : 20140908_0001_1000
회원: 0_1_1 0은 무효 클릭에 해당하고, 1은 브라우저 테이블의 QQ 브라우저에 해당하고, 1은 지역 테이블의 상하이에 해당합니다
점수:10

A, B, C의 3가지 해결방안이 있다고 가정합니다
말씀하신 대로 열쇠는 이렇게 생겼을 거에요
20140908_0001_A
20140908_0001_B
20140908_0001_C
제가 말씀드리는 보관방법은
키:20140908_0001
회원:validORinvalid_browser_region_클릭수
점수:해상도

이렇게 검색하면 실제로는 20140908일의 0001페이지(단지 1개의 키)만 가져온 다음 범위 A 해상도를 보고 해당 멤버를 보면 구분하기 좋지 않기 때문에 유용하지 않습니다. 여기에 요율을 입력하는 것은 의미가 없습니다. 이 경우 zset을 사용하는 데 문제가 있습니다.

위 내용은 예시일 뿐입니다! 실제로 더 좋은 방법이 있습니다. 질문을 수정하고 요구 사항을 이해한 후 새로운 접근 방식을 생각해 냈습니다.

zset:데이터 세트
키:날짜-페이지-해상도
점수: 좌표(x와 y를 숫자로 바꾸는 것을 생각해 보세요)
회원 : 브라우저-지역-유효클릭수-무효클릭수

날짜가 선택 범위가 되는 경우 날짜를 구체적으로 저장하기 위해 이 세트가 필요합니다. 이를 날짜 세트라고 합니다
키:페이지
점수:날짜
구성원:데이터 세트 키
날짜 세트의 목적은 데이터 세트 키를 색인화하는 것입니다. key()를 사용하는 방법은 모든 검색을 수행하므로 매우 느립니다. 귀하의 예는 특정 날짜입니다. 날짜 범위가 없으므로 날짜 설정이 불필요할 수 있음을 이해합니다. 마찬가지로 해결 방법이 너무 많아 마스터할 수 없는 경우 이 설정을 모방하여 컬렉션을 만들 수도 있습니다. 열쇠!

다음 두 좌표는 zset인데 잘 살펴보지 않았네요.

아래에 4개의 쿼리 예를 제시하셨습니다

특정 날짜에 특정 페이지에 대한 클릭수, 즉 총 유효 클릭수 + 총 무효 클릭수를 쿼리하는 쿼리입니다.

B 특정 날짜의 특정 페이지와 특정 해결 방법에 대한 총 유효 클릭 수와 총 무효 클릭 수를 쿼리합니다

C 특정 페이지의 모든 좌표점과 클릭 수, 특정 날짜의 특정 해상도를 쿼리합니다

D 프레임 선택 쿼리(범위 쿼리와 동일) 특정 범위(예: 100

A: 3가지 해상도가 있다고 하셨는데 키 뒤에 3가지 해상도를 추가하시면 범위 0과 -1이 모두 포함됩니다
20150415-페이지1-1380,20150415-페이지1-1190,20150415-페이지1-1000

B: 하나의 키를 확인하고 범위 0과 -1을 얻으면 좋습니다.
20150415-page1-1380

C: 좋습니다. 처음 두 명도 좌표를 얻을 수 있지만 쇼는 없습니다

D: 좌표 세트를 사용해 키를 얻은 후 데이터 세트 범위 좌표를 확인하세요

다 쓰고나서 오타 확인을 하다가 작은 문제를 발견했는데, 지역별로 유효한 브라우저와 잘못된 브라우저를 기록해 둬야 할 것 같죠? 필요하지 않은 경우 데이터 세트의 구성원은 유효한 숫자와 잘못된 숫자를 기록하면 됩니다. 필요한 경우 해당 지역의 브라우저 수를 기반으로 디자인을 고려해야 합니다. .

Ty80

어쩌면 Redis에 대한 저의 이해가 질문자의 생각과 다를 수도 있습니다. 제 생각에 따르면 위의 요구 사항을 충족하는 것은

로그 기억, ETL 전송 데이터

드디어 출시되었습니다

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿