Reputation: 14874
In order to boost my app's performance I'd like to avoid hitting database as much as possible. So to update page visits counter, I'd like to use redis cache and it's ability to expire keys.
There are thousands of pages and each page can be visited several times per second.
Here is the pseudo-code of what I think about:
- Define key: `pagetimer:<id>` as timer, which expires after 10 minutes
- Define key: `page:<id>:<visits>` as the page.visits counter
- After each page visit, If `pagetimer:<id>` exits:
page:<id>:<visits>++
else:
//`pagetimer:<id>` has expired so:
flush page:<id>:<visits> value to database's page.visits
define new pagetimer:<id>`
set page:<id>:<visits> to the value obtained from database's page.visits
page:<id>:<visits> ++
I'm wondering what could be the flaws of such strategy? And whether there is a better solution for this?
Upvotes: 0
Views: 626
Reputation: 22981
what could be the flaws of such strategy
It has the following flaws:
Your code is not atomic, and it has race condition. So you might lose some visit counts, and might hit database more than you want.
If you try to make the code atomic, e.g. use transaction or Lua script, you'll have performance problems: when you read or write the database, it blocks Redis.
If a page is never visited after the timer expired, the counter won't be flush to database.
whether there is a better solution for this
Yes, there is. However, it's much more complex, and need to solve the above problems. I'll give you some hits.
You need to have multiple counters for each page, e.g. create a new counter every 10 minutes, or every 1000 counts.
You need to update the database in another thread or process.
Upvotes: 3