开发者

Redis Track Hits

I have a simple daily hit counter on my site that I want to use Redis as the datastore for.

Simply because redis has an expire, I dont have to set up a cron to clear the data down. Plus I want to try it out.

I store daily hits on a URL basis.

How can I store the daily hits for a url then have them expire at the end of the day.

For example:

incr today:www.google.com           >> 1
incr today:www.google.com           >> 2
incr today:www.google.com           >> 3
incr today:www.yahoo.com            >> 1
incr today:www.yahoo.com            >> 2

How do I have these counters expire at the end of the day? If I do an expire, it resets the开发者_如何学Python counters.

I feel like my thought process is off. Am I doing things backwards?


You need to be using the current date as key rather than "today".

Set up a hash for the current date, with each url being a key within that hash. Your update would then be

HINCRBY 101021 www.google.com 1

and you can use the DEL command to remove the entire hash for a day once you no longer want to keep the data - maybe set up a manually triggered script that calls DEL for everything between 1 and 2 months old.

Setting expiry on the hash would probably also work though I haven't tried it - using a different key for each day means you aren't relying on expiry happening at a precise time like you would be with a "today" key.


Another option is to use redis >= 2.1.3. From that version on, expire works the way you want. I'm using 2.1.5 (from git) to do this same thing. I use both expire and a method similar to what Tom describes. I place the date in the key, and I set an expiration. With redis >= 2.1.3 you can set expire on an incremented key without it resetting the counter.

The reason for both is a) I store more than one day and b) if the expired keys are still there for whatever reason I'm not querying for them when getting stats for today. For example the hash: SERVER with key YEAR:MONTH:DAY:URL is incremented and an expiration set for today+3 days. Works like a charm.


I did solution recently for analytics built into my app:

incr www.google.com 1

then nightly, in a cron job:

getset www.google.com 0

getset atomically returns the value and sets it to the new value, which resets your counters without missing a single hit.

I also happen to:

lpush yearly:www.google.com <value from getset>
ltrim yearly:www.google.com 0 364 (this is optional)

this puts "last night's" value onto a list. the list is optionally trimmed to store up to one year's values. (this is really effective when doing 60-minute sparklines)


A more straightforward option would be as suggested, to use the current date. What I do is use the year month day as key. But rather than use a hash, I simplify matters by appending the page to the date as key.

For example:

INCR 20110425:www.google.com
INCR 20110424:www.yahoo.com
...
INCR 20110426:www.google.com

To make it easier to retrieve information afterwards another solution I use where appropriate is to store the information in a sorted set.

For example:

$rank = ZRANK hits:www.google.com 20110425
ZADD hits:www.google.com ($rank + 1) 20110425

With this variation you can simply ask the following to get all hits for www.google.com:

ZRANGE hits:www.google.com 0 -1

or

ZREVRANGE hits:www.google.com 0 -1

or

SORT hits:www.google.com ...

Hope this is some help

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜