我现在有个需求
需要记录页面点击数据,上游吐到redis中,
上游怎么吐到redis中对我们来说是透明的,
我们只用关心redis中如何存储就好。
查询某天某页面下所有点击数,即有效点击总数
+无效点击总数
查询某天某页面某分辨率下 所有有效点击总数
和无效点击总数
查询某天某页面某分辨率下所有的坐标点及点击数
框选查询(相当于范围查询) 查询某天某页面某分辨率下 某个范围(比如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.
zset
来实现需求。一个 zset 记录某天某页面某分辨率的数据
key
为 date_pageid_分辨率 member为: 有效OR无效_ 浏览器_ 地区score
为点击数
举例:key
: 20140908_0001_1000member
: 0_1_10对应无效点击,1对应浏览器表中的QQ浏览器,1对应地区表中的上海
score
:10
每个坐标点相关数据都用一个对应的
zset
记录key
为 date_pageid_分辨率_ 横坐标_ 纵坐标member
为: 有效OR无效浏览器地区score
为点击数
举例:key
: 20140908_0001_1000_23_478member
: 0_1_20对应无效点击,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的辅助查询zetkey
为: date_pageid_分辨率yeg.20140908_0001_1000_y
member
: 为 date_pageid分辨率_ 横坐标 _纵坐标eg.20140908_0001_1000_23_478
score
为:横坐标y的值eg.478
x的辅助查询zet
key
为: date_pageid_分辨率xeg.20140908_0001_1000_x
member
: 为 date_pageid分辨率_ 横坐标 _纵坐标eg.20140908_0001_1000_23_478
score
为:横坐标X的值eg.23
查询速度太慢
举例 :比如我想一次取出某天某页面某分辨率下所有的点,
可能需要一次查询几万个keyeg. 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慢查询问题。
不知道大家针对我
现在的实现方案有什么更好的优化策略
或者针对查询需求有没有什么更好的设计方案
,
新人第一次发帖,感谢@暗雨西喧
对排版的提醒。
请大家多指教。
L'interrogation avec de nombreuses clés est lente. Cela fait-il référence au zset réellement cliqué lors de la dernière requête ?
Je ne sais pas combien de résolutions il y aura ? Vous pouvez modifier la clé de zset non pas pour avoir une résolution, mais pour avoir une résolution en valeur. Cela peut réduire beaucoup de clés. Si vos conditions de recherche ont une résolution, vous pouvez effectuer un filtrage après avoir recherché une valeur, et la vitesse devrait être très élevée. rapide.
C'est comme demander à l'utilisateur de dessiner manuellement une zone de recherche. Pouvez-vous envisager de modifier cette condition pour inclure l'image entière ? Découpé en 10 parties (100 parties, 10 000 parties). Chaque partie est un carré. La condition ne peut sélectionner qu'un certain carré, plutôt que de simplement le dessiner au hasard. De cette manière, les données de chaque carré peuvent être « résumées » de manière prévisible. .
Parlons-en d'abord et voyons si cela aide. Si vous avez encore besoin de l'optimiser, vous pouvez modifier la description de la requête dans la question. Il y a certains endroits que vous pouvez rattraper, mais je ne sais pas si vous le pouvez. Je veux exprimer cela, je vais donc vous en donner un simple. Veuillez écrire l'exemple en détail et utiliser la composition, cela a l'air très fatiguant
Je les ai écrits séparément. Voici la réponse après avoir corrigé la question
Tout d'abord, vous n'utilisez pas l'essence de zset, qui trie automatiquement l'index selon scop. Il semble que vous ne devez pas comprendre la résolution que j'ai mentionnée ci-dessus lorsque vous la mettez en valeur. exemple
Supposons qu'il y ait 3 résolutions : A, B, C
D'après ce que vous avez dit, la clé ressemblera à ceci
20140908_0001_A
20140908_0001_B
20140908_0001_C
La méthode de stockage dont je parle est
clé :20140908_0001
membre : validORinvalid_browser_region_number de clics
score:résolution
Lors d'une recherche comme celle-ci, il vous suffit en fait d'obtenir la page 0001 du jour 20140908 (juste 1 clé), puis de sélectionner la résolution A et de regarder ses membres. Ce n'est pas utile car ce n'est pas agréable à distinguer. Cela ne sert à rien de mettre le taux ici. L'utilisation de zset pose des problèmes dans ce cas.
Ce qui précède n'est qu'un exemple ! En fait, ne faites pas ça. Il existe une meilleure façon. Après avoir révisé la question et compris les exigences, j'ai proposé une nouvelle approche.
zset:ensemble de données
clé : date-page-résolution
score : coordonnées (pensez à transformer x et y en nombre)
membre : navigateur-région-nombre de clics valides-nombre de clics invalides
Si la date devient une plage facultative, cet ensemble est nécessaire pour stocker la date spécifiquement. Nous l'appelons : ensemble de dates
. clé:page
score :date
membre : clé de l'ensemble de données
Le but de l'ensemble de dates est d'indexer la clé de l'ensemble de données. Votre méthode d'utilisation de key() est très lente car elle effectuera une recherche complète. Votre exemple est un certain jour. Je comprends qu'il peut n'y avoir pas de plage de dates, donc le jeu de dates peut être inutile. De même, s'il y a trop de résolutions et qu'il est impossible de le maîtriser, vous pouvez également imiter cet ensemble pour créer une collection. de clés !
Les deux coordonnées suivantes sont zset. Je ne les ai pas regardées attentivement. Réfléchissons bien à l'utilisation de zset.
Vous avez donné 4 exemples de requêtes ci-dessous
A : Vous avez dit qu'il y avait 3 résolutions, puis ajoutez 3 résolutions après la clé, les plages 0 et -1 sont toutes incluses
20150415-page1-1380,20150415-page1-1190,20150415-page1-1000
B : C'est génial. Cochez simplement une touche et obtenez la plage 0 et -1
20150415-page1-1380
C : D'accord, les deux premiers peuvent aussi obtenir les coordonnées, mais vous n'avez pas de spectacle
D : Après avoir utilisé votre ensemble de coordonnées pour obtenir la clé, vérifiez les coordonnées de la plage de l'ensemble de données
Après avoir tout écrit, j'ai trouvé un petit problème lors de la vérification des fautes de frappe. Il semble que vous deviez enregistrer les navigateurs valides et invalides dans chaque région ? Si cela n'est pas nécessaire, les membres de l'ensemble de données peuvent simplement enregistrer des numéros valides et invalides. Si cela est nécessaire, la conception doit être prise en compte en fonction du nombre de navigateurs dans la région. Votre question ne semble pas introduire cet aspect. .
Peut-être que ma compréhension de Redis est différente de celle de la personne qui pose la question. Selon mon idée, atteindre les exigences ci-dessus peut être
.N'oubliez pas le journal, etl transfère les données
Enfin disponible