数据库是sqlserver,已分表,每天一张数据表,大概3000W数据一天
需求是每次别人访问,都必须查询一下当天的访问状态,比如访问A页面多少次,访问B页面多少次(没办法,需求是这样)
还要通过一定条件去判断是否是代理(也是查数据库)
之前是按cookies,但这东西不靠谱,很多相同的IP但空cookies过来
但每次都要连接一次数据库查几百万数据,性能又吃不消,而且是高并发状态,高的时候可能1分钟好十几万访问量
也考虑过nosql,但不熟悉,请问高人是否有解决方案
------------抱歉,数字写错了,不是300W而是3000W一天(3000W是包括所有访问轨迹,包括访问JS,img,css等等)
其实就是个流量系统的日志和防火墙类似的功能,每个访问的目标,要按N个条件去比较数据库里的数据,以判断来的是真实用户还是机器人(很多刷子),包括了IP(一定时间内重复次数,黑名单),UA,来源地址,cookies等等
最主要的问题是高并发,可能会有1分钟内十几万的并发量,而且所有的访问日志都要再进入这个表里。查询条件比较复杂,因为涉及多个条件,而且还有一段时间内的重复IP判断,甚至是虽然不同IP(可能是加了代理刷的)但要判断UA和reffer还有其他的一些条件做出相似性的分数判断,差不多有些每次都要大数据分析的概念。我就在想,这种情况下,怎么个解决方案比较好。。。
用redis的自增命令吧.
没搞懂啊,你这个300w数据,根据ip做一个索引,至于那么慢么?
再说,300w又不是很大的数据量。而且你还可以做缓存把查询的结构存一下。
实在不行,扔Mongo(比较像SQL的NOSQL),查询也是不会慢。
我的意见是分时段聚合。3000w这个表作为数据源表。然后每个时间段(每小时),利用定时任务聚合到某个特定的表上,然后将源表的多余记录干掉。这样的话,基本上数据量就会很小,查询的时候,只需要union下两张表的数据即可。
查数据库的这个过程要挪出来,不管你是什么规则匹配或是什么其他的玩意,就算不用nosql你把规则信息写配置文件里面一次性加载都可以。
统计这个用redis自增可以,如果仅仅只是统计某个页面ip去重的总访问量可以用hyperloglog(省空间,但有一定误差,不过误差很低),不考虑空间开销的话hash也可以(但看你的场景可能到了第二天时前一天的hash就没用,这个时候要注意前面一天hash的删除或者过期可能会使redis卡一下)
update:
你附加问题中提到的规则也是可以拿到缓存里面来的啊,以你可能出现的规则中也出现需要查询的场景(比如黑名单),这种可以直接在缓存中exists判断下就完了
单位时间内重复ip也容易,你直接加个有expire的key,每次去incr下,如果incr的结果大于你的设置值就拦下来了,其他的以此类推
归根结底如果一分钟几十万次调用只能允许极少量的请求直接落到db上,否则需要对db的硬件需求量就大了
就是一个以页面和日期(天)为索引的列(广义列)和一个计数列 的表就解决了。
请求进来直接匹配此索引,而该表数量肯定是非常有限的,而且这种写入不必等待,你还想抛开这种等待,可以有单独的此任务的任务队列去执行处理。
根本性的解决方法是在原来的基础上增加一个统计表,统计表的数据是在统计数据新增的时候,另外再写入,每个页面一条统计数据,累计统计访问量,具体的还可以再分出更多字段,比如来源自搜索引擎的点击。至于ip的重复访问,就需要再另建一个表来统计,每个ip一条数据……所有的工作量集中在统计写入的时候处理。如果这种统计是在页面前端用js调用的形式来统计,放在页尾基本也不会影响网页打开速度了。
然后查看的时候调用统计表,每个统计表如果要看详细数据,再点击去检索那详细表的数据出来,通常这个也只是管理后台在用,对整站不会有多大性能上的影响。。。
如果按你原来的思路,只能硬统计,没办法的事情。
实在不行,找一台机器专门做缓存。频繁使用的,缓存一下,
还有一种,关键字既然是IP,考虑一下,数据再按照IP分表存一下。临时。
这个东西还是程序来搞吧
每次访问就在Redis里面搞一个计数器记录起来
查询的时候。就直接读缓存就可以了