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

我现在有个需求

需要记录页面点击数据,上游吐到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伐。

membalas semua(2)
PHPzhong

Iaitu, apabila terdapat banyak kekunci, kelajuan pertanyaan adalah sangat perlahan

Pertanyaan dengan banyak kekunci adalah perlahan. Adakah ini merujuk kepada zset yang sebenarnya diklik dalam pertanyaan terakhir?

Saya tidak pasti berapa banyak resolusi yang akan ada? Anda boleh mengubah suai kunci zset untuk tidak mempunyai resolusi, tetapi untuk mempunyai resolusi dalam nilai Ini boleh mengurangkan banyak kunci Jika keadaan carian anda mempunyai resolusi, anda boleh melakukan beberapa penapisan selepas mencari nilai, dan kelajuannya harus sangat cepat.

Tetapi kelakuan pemilihan kotak adalah kerana julatnya berubah
Pertanyaan pemilihan bingkai (bersamaan dengan pertanyaan julat) Pertanyaan pada hari tertentu, halaman tertentu, resolusi tertentu
Jumlah bilangan klik yang sah dan jumlah bilangan klik tidak sah pada titik koordinat dalam julat tertentu (seperti 100<x<1000,30<y<600).

Ia seperti meminta pengguna melukis kawasan secara manual untuk carian Bolehkah anda mempertimbangkan untuk menukar syarat ini untuk memasukkan keseluruhan imej? Potong kepada 10 bahagian (100 bahagian, 10,000 bahagian. Setiap bahagian adalah segi empat sama. .

Mari kita bincangkan perkara ini dahulu dan lihat jika ia membantu Jika anda masih perlu mengoptimumkannya, anda boleh mengubah suai perihalan pertanyaan dalam soalan Terdapat beberapa tempat yang boleh anda tebus, tetapi saya tidak tahu sama ada anda nak luahkan ni, jadi saya bagi yang simple je Sila tulis contoh secara detail dan guna typesetting, nampak sangat memenatkan


Saya menulisnya secara berasingan. Berikut ialah jawapan selepas anda membetulkan soalan itu

Pertama sekali, anda tidak menggunakan intipati zset, yang secara automatik menyusun indeks mengikut skop Nampaknya anda mesti tidak memahami resolusi yang saya nyatakan di atas apabila anda meletakkannya dalam nilai contoh

Zset merekodkan data halaman tertentu dan peleraian tertentu pada hari tertentu
Kuncinya ialah date_pageid_resolution dan ahlinya ialah: sah ATAU invalid_browser_region
skor ialah bilangan klik
Contoh: kunci : 20140908_0001_1000
ahli: 0_1_1 0 sepadan dengan klik tidak sah, 1 sepadan dengan pelayar QQ dalam jadual penyemak imbas, 1 sepadan dengan Shanghai dalam jadual wilayah
markah:10

Andaikan terdapat 3 resolusi: A, B, C
Menurut apa yang anda katakan, kunci akan kelihatan seperti ini
20140908_0001_A
20140908_0001_B
20140908_0001_C
Kaedah penyimpanan yang saya maksudkan ialah
kunci:20140908_0001
ahli:validORinvalid_browser_region_bilangan klik
skor:peleraian

Apabila mencari seperti ini, anda sebenarnya hanya perlu mendapatkan halaman 0001 hari 20140908 (hanya 1 kunci), dan kemudian julat resolusi A dan lihat ahlinya. Ini tidak berguna kerana ia tidak bagus untuk dibezakan. Tiada gunanya meletakkan kadar di sini. Terdapat masalah dengan menggunakan zset dalam kes ini.

Di atas hanyalah contoh! Sebenarnya, jangan lakukan ini. Terdapat cara yang lebih baik Selepas anda menyemak soalan dan memahami keperluan, saya menghasilkan pendekatan baharu.

zset:set data
key:date-page-resolution
skor: koordinat (fikir untuk menukar x dan y menjadi nombor)
ahli: pelayar-rantau-bilangan klik yang sah-bilangan klik tidak sah

Jika tarikh menjadi julat pilihan, set ini diperlukan untuk menyimpan tarikh secara khusus Kami memanggilnya: set tarikh
kunci:halaman
markah:tarikh
ahli: kunci set data
Tujuan set tarikh adalah untuk mengindeks kunci set data Kaedah anda menggunakan key() adalah sangat perlahan kerana ia akan melakukan carian semua. Contoh anda ialah hari tertentu Saya faham bahawa mungkin tiada julat tarikh, jadi set tarikh boleh jadi tidak diperlukan Begitu juga, jika terdapat terlalu banyak resolusi dan mustahil untuk dikuasai, anda juga boleh meniru set ini untuk membuat koleksi. daripada kunci!

Dua koordinat seterusnya ialah zset. Saya tidak melihatnya dengan teliti.

Anda memberikan 4 contoh pertanyaan di bawah

A pertanyaan bilangan klik pada halaman tertentu pada hari tertentu, iaitu, jumlah bilangan klik yang sah + jumlah bilangan klik tidak sah

B Tanya jumlah klik yang sah dan jumlah klik tidak sah pada halaman tertentu dan resolusi tertentu pada hari tertentu

C Tanya semua titik koordinat dan bilangan klik pada halaman tertentu dan resolusi tertentu pada hari tertentu

Pertanyaan pemilihan bingkai D (bersamaan dengan pertanyaan julat) Tanya jumlah klik yang sah dan jumlah bilangan klik tidak sah titik koordinat dalam julat tertentu (seperti 100<x<1000,30<y<600) di resolusi tertentu pada hari tertentu

J: Anda berkata terdapat 3 resolusi, kemudian tambah 3 resolusi selepas kunci, julat 0 dan -1 semuanya disertakan
20150415-halaman1-1380,20150415-halaman1-1190,20150415-halaman1-1000

B: Ini bagus cuma semak satu kunci dan dapatkan julat 0 dan -1
20150415-halaman1-1380

C: Baiklah, dua yang pertama juga boleh mendapatkan koordinat, tetapi anda tidak mempunyai rancangan

D: Selepas menggunakan set koordinat anda untuk mendapatkan kunci, semak koordinat julat set data

Selepas menulis semuanya, saya mendapati masalah kecil semasa menyemak kesilapan menaip Nampaknya anda perlu merekodkan penyemak imbas yang sah dan tidak sah di setiap wilayah? Jika tidak perlu, ahli dalam set data hanya boleh merekodkan nombor yang sah dan tidak sah Jika perlu, reka bentuk perlu dipertimbangkan berdasarkan bilangan pelayar di rantau ini .

Ty80

Mungkin pemahaman saya tentang redis berbeza dengan penyoal Mengikut idea saya, untuk mencapai keperluan di atas mungkin

Ingat log, data pemindahan etl

Akhirnya tersedia

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan