【redis儲存結構設計】儲存座標點及其多維度點擊數
伊谢尔伦
伊谢尔伦 2017-04-22 08:59:44
0
2
845

我現在有個需求

需要記錄頁麵點擊數據,上遊吐到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

即key很多的時候,查詢速度很慢

key很多查詢慢,指的是拿最後查詢實際點擊的zset做的事情嗎?

不太清楚解析度會有多少種?可以修改zset的key不帶分辨率,而是在value中帶分辨率,這樣能減少很多的key,如果你搜尋條件有分辨率可以在search出value後做一下過濾速度應該很快。

但是框選行為 因為範圍不定
框選查詢(相當於範圍查詢) 查詢某天某頁某解析度下
某個範圍(例如100

就好像是讓用戶手動劃一片區域出來做搜索,可以考慮更改這個條件,把整個圖片?切割成10份(100份,10000份)每一份就是一個方格,條件只能選取某一個方格,而不是隨便劃,這樣可以預測的把每個方格中的資料先「匯總」下。

先說這些,你看看有沒有幫助,如果還是需要再優化,你修改一下問題中的查詢描述,有些地方可以腦補,但不知道你是不是要表達這個意思,所以舉個簡單點的範例寫的詳細點,用用排版,這樣看著很累


我分開寫,這下面是你改過問題後的

首先說你沒有使用出zset的精華,根據scop自動排序索引,看來我上面說的分辨率放到value裡面你一定沒看懂,我舉個例子

一個 zset 記錄某天某頁某解析度的資料
key 為 date_pageid_解析度 member為: 有效OR無效_ 瀏覽器_ 地區
score 為點擊數
舉例: key : 20140908_0001_1000
member: 0_1_1 0對應無效點擊,1對應瀏覽器表中的QQ瀏覽器,1對應地區表中的上海
score:10

假設有3種解析度:A,B,C
照你說的存key會是這樣
20140908_0001_A
20140908_0001_B
20140908_0001_C
我說的存法是
key:20140908_0001
member:有效OR無效_ 瀏覽器_ 地區_ 點擊數
score:解析度

這樣search時,其實只需要先拿到20140908這天的0001頁面(只是1個key),然後再rang A分辨率,看它的member就可以了,這樣用不好,因為不nice分辨率放這裡沒啥意思,這個case用zset本身就有問題。

以上只是舉了個例子!實際上別這麼做了有更好的辦法,你修改問題後了解了需求我想到了一種新的做法。

zset:data set
key:日期-page-解析度
score:座標(想一下把x,y變成一個數字)
member:瀏覽器-地區-有效點選數-無效點擊數

如果日期變成可選的範圍需要這個set,專門存日期,我們把它叫做:date set
key:page
score:日期
member:data set key
date set的目的是用來索引data set key,你使用key()這種做法本身就特別慢,因為它會去all search。你的例子是某天,我理解可能沒有日期區間,所以date set可以不用了,同樣如果分辨率過多,不可能掌握的話,也可以模仿這個set做一下key的合集!

再來是2個座標zset,我沒有仔細看,用zset好不好的斟酌一下吧。

以下你舉了4個查詢範例

A查詢某天某頁下所有點擊數,即有效點擊總數+無效點擊總數

B查詢某天某頁某解析度下 所有有效點擊總數和無效點擊總數

C查詢某天某頁某解析度下所有的座標點及點擊數

D框選查詢(相當於範圍查詢) 查詢某天某頁面某解析度下 某個範圍(例如100

A:你說有3種分辨率,那就在key後面加上3種分辨率吧,range 0,-1全拿
20150415-page1-1380,20150415-page1-1190,20150415-page1-1000

B:這個好啊,就查一個key的,range 0,-1全拿
20150415-page1-1380

C:好吧,前2個也能拿到座標的,只不過你沒有show而已

D:用你的座標set拿到key後,再查data set range 座標

都寫完,檢查錯字時發現個小問題,似乎你需要記錄每個地區瀏覽器的有效和無效?如果不是必須的data set中的member只是記錄有效無效數字即可,如果是必須的需要看地區瀏覽器的數量來考慮設計了,這方面你問題中好像沒怎麼介紹。

Ty80

可能我對redis的理解和題主的不一樣,按照我的想法要實現如上需求可能是

記log ,etl轉資料

最後可查詢

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板