针对用户 IP,返回随机 URL,并需要存储 URL 到数据库,这个随机 URL 数据可以每天清空一遍,用什么方案性能最好?

2017-10-11 19:47:02 +08:00
 Loyalsoldier

RT,例如假设,每天有 50W IP 的访问,用户进入网站,会随机返回一个 302 的响应,然后跳转到一个随机的 URL。用户第二次进来,会查询数据库中是否存在该 IP,存在,则跳转到第一次访问的随机 URL。

也就是说,要做一个 IP 和 随机 URL 的映射关系表,这个表数据量很大,假设是 50W,这些数据可以在一天后清除的。怎么做才能尽可能实现高性能,不影响网站用户体验?

目前想到 Redis,但是好像 Redis 每秒只能查询 20W 次?那要遍历 50W 次的话,好像挺久的……

非科班设计师出身,轻喷……

3303 次点击
所在节点    程序员
27 条回复
qiayue
2017-10-11 19:50:28 +08:00
“ Redis 每秒只能查询 20W 次”
这个结论哪里来的?
187j3x1
2017-10-11 19:53:46 +08:00
hash table 原理嘛? 50 万 50 亿都是差不多速度的,吃内存而已
Loyalsoldier
2017-10-11 20:01:48 +08:00
@qiayue #1

http://www.runoob.com/redis/redis-intro.html

我还说高了…………之前看过一个文档写着,但是一时间找不到了
yankebupt
2017-10-11 20:13:28 +08:00
为什么要遍历?由于 ip 地址特性 int32(ipv4)可以加速不用遍历的。
一提到这个就想起最近的动态路由屏蔽表...估计规则数也比你那个不少...那个是真的大访问量...我一直在想那个是怎么跑起来的...有可能是特殊硬件吧?...
我看到第一个回复查询 20W 次,还以为 20W+访问量.....
yankebupt
2017-10-11 20:16:33 +08:00
总有股维和感,我总觉得楼主的意思是不是反过来,是不是想根据 url 记录如果没有随机返回一个 ip 并绑定。
Loyalsoldier
2017-10-11 20:20:49 +08:00
@yankebupt #5

不是,就是根据 IP,返回一个随机 URL 并存进数据库。当天的后续访问,就查询数据库,取出该随机 URL,跳转到该 URL
yankebupt
2017-10-11 20:34:40 +08:00
我觉得楼主如果之后回帖:
我发现一个好方法,把库分成两部分,一部分存国内 ip 和 url,一部分存国外 ip 和 url...根据访问热度和管理要求实现不同查询性能......实现 90%以上的满意度...
的话
我会后悔在这个主题回帖的.....

所以楼主,稍微详细一点说明你的实际使用情况?
还有为什么就选定 redis 了
yankebupt
2017-10-11 20:45:16 +08:00
不要误解我。我是说大多数情况下技术人员会根据热度,分不同的使用用户,高频用户给一个很小的高速查询库,响应极其迅速,查不到再查之外的逐步扩大。但是涉及你这种情况如果这样做实际上是违背网络公平性的,会加大非高频用户的延迟,加之我 redis 基本没碰过,所以完全不能给出有效建议,请见谅。
xmcp
2017-10-11 20:46:13 +08:00
二分查找是 O(logN) 级别的,50W 肯定没问题呀。楼主要是挨个遍历强行卡成 O(N) 肯定就 gg 了呀……

另外不知道你的需求是什么,如果你只需要“清空所有映射”,不需要“删除特定映射”的话,不妨直接弄个 hash 的算法,URL=hash(salt+IP),想要清空的话换个 salt 就行了,查询 O(1),岂不美哉?
Loyalsoldier
2017-10-11 20:53:24 +08:00
@yankebupt #7

用户从 a.com (入口域名) 访问网站,后端拿到该用户的 IP 地址(假设是 1.1.1.1),随机从可选的 URL 中返回一个给该用户,假设返回 b.com (目标域名),这时候 1.1.1.1 就对应 b.com 。在当天内,用户 1.1.1.1 再次从 a.com 访问进行访问,为了保证用户在当天内看到同样的页面内容,这时候需要给用户返回跟第一次访问时一样的 URL。查询数据库发现,1.1.1.1 对应 b.com ,这时候给用户 1.1.1.1 返回 b.com

但是当一天内访问的用户量足够大的时候,查询“目标域名”的操作就会很慢了吧,所以问,用什么技术方案来实现这个需求,用户能最快访问到目标 URL
Loyalsoldier
2017-10-11 20:54:54 +08:00
@xmcp #9

用户从 a.com (入口域名) 访问网站,后端拿到该用户的 IP 地址(假设是 1.1.1.1),随机从可选的 URL 中返回一个给该用户,假设返回 b.com (目标域名),这时候 1.1.1.1 就对应 b.com 。在当天内,用户 1.1.1.1 再次从 a.com 访问进行访问,为了保证用户在当天内看到同样的页面内容,这时候需要给用户返回跟第一次访问时一样的 URL。查询数据库发现,1.1.1.1 对应 b.com ,这时候给用户 1.1.1.1 返回 b.com

但是当一天内访问的用户量足够大的时候,查询“目标域名”的操作就会很慢了吧,所以问,用什么技术方案来实现这个需求,用户能最快访问到目标 URL
lianyue
2017-10-11 20:56:27 +08:00
这需要 考虑这么多干嘛 动态网页 基本每次打开都会有查询 正常 以内

其实普通数据库 什么的
id, ip date
就好了 多一个字段超过 24 小时自动过期 根本不需要什么删除

或者每天一个新表 为什么非要操作 删除旧的数据


表名比如
access_2017_10_11
access_2017_10_12
access_2017_10_13

结构
id, ip


实现方式很多
binux
2017-10-11 20:58:13 +08:00
随机选一个域名是 O(1) 的,查询一个 ip 对应的域名也是 O(1) 的,不管用户量有多大,就算 13 亿它也是一样的速度。
syhsyh9696
2017-10-11 20:59:32 +08:00
为何不是根据当前的时间和 ip 地址生成当天的 temp url ?
xmcp
2017-10-11 21:03:25 +08:00
@Loyalsoldier 这用什么数据库呀?直接用 IP 地址做种子生成随机数呀。伪(?)代码如下:

SALT='foo' # 改这个数来重置所有用户访问到的网址
WEBSITES=['b.com','c.com','d.com']

def get_url(ip):
___ r=random.Random()
___ r.seed(SALT+str(ip))
___ return r.choice(WEBSITES)

如果真要上数据库的话 redis 也不是不行,人家 redis 也有 hash 数据结构: http://www.runoob.com/redis/redis-hashes.html,O(logN) 肯定能满足正常网站的速度要求的。
yankebupt
2017-10-11 21:12:29 +08:00
@Loyalsoldier 但是 ip 可以 hash 的...
不懂 hash 会加速的道理也没关系,这么解释一下,假设你为 0.0.x.x-255.255.x.x 的 ip 建 65536 张表,则每张表最多也就是 65536 个记录(实际每个记录都会很少会更快,因为需要访问一次才有记录)。只查对应的表只需遍历很少的记录....

不过我愈发觉得楼主可能是在钓鱼...专门钓我们这种不懂 memcached/LRU 的...
yankebupt
2017-10-11 21:17:23 +08:00
@xmcp 也好,但我看到楼主说了每天数据可以清空,可能意味着楼主想在 SALT 里加入当前日期或者有自己的生成算法,咱们继续看看楼主怎么发展吧....
bydmm
2017-10-11 22:03:24 +08:00
楼主你逗我把,

ip 到一段字符串的映射关系根本不用遍历整个 redis 空间啊。 他们之间是 hash 映射的关系。

你用 ip 作为 key,url 作为 value,再多 ip 都是一次好吗。。
dbw9580
2017-10-11 22:13:12 +08:00
for ip in seen_ips: if ip != remote_ip, continue; else return ip2urltable[ip]

op 的思考方式
gstqc
2017-10-11 22:30:46 +08:00
用 IP 做 key 查询不是 O(n)的,是 O(1)
50 万数据小得可怜,估计几百 M 内存搞定

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/396886

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX