Reputation: 159
I am trying to figure out the most straightforward and safe way to count the number of active sessions using a memcached storage option. With DB based session storage, I can just count the number of rows in the table but can't do the same thing with memcached.
Thanks, Vikram
Upvotes: 2
Views: 1980
Reputation: 286
I know this post is really old, but I thought I'd add a potential solution here and see what kind of comments come in from the community.
We're considering moving our sessions to memcached since we're using it for fragment caching (and other things). This approach is working on my machine but haven't had a chance to clean up the code and test it out in a more robust environment.
The solution is pretty straight forward. It uses a key based on hour:minute and increments/decrements the keys when a session is extended. The bucket (key) the session is put into is returned and stored in the session. The next time the session hits the app, the previous bucket it was put in is provided to the count method. That way a session can move between keys (moved from previous bucket to new bucket)
Here is the method:
def count(previous_bucket)
# All this does is construct a key like this:
# _session_counter_10:15
key = KEY_PREFIX + time_key(Time.now.hour, Time.now.min)
# do nothing if previous bucket = key
return key if previous_bucket.present? && key.eql?(previous_bucket)
# Increment the count in the cache
Rails.cache.increment(key, 1, expires_in: 30.minutes)
# If there is a previous bucket, decrement the count there
if previous_bucket.present?
Rails.cache.decrement(previous_bucket, 1)
end
# Return the key used so it can be stored in the session which was counted. This will be returned on the next
# call to bump to keep the numbers accurate
return key
end
To use, the calling method is doing this:
counter = SessionCounter.new
session[:counter_bucket] = counter.count(session[:counter_bucket])
To get a count of sessions in a given time period, you can simply construct an array of keys for the time period, then use read_multi to retrieve the counts in that time.
For example:
keys = ["_session_count_10:15","_session_count_10:14","_session_count_10:13"]
values = Rails.cache.read_multi(*keys)
Values is a hash which will contain any matching keys. Simply sum up the values of the keys to get the count in that time period.
Question:
Update:
We've implemented this pattern and put it into production. It has been working really well for us and no performance issues have appeared yet.
Upvotes: 0
Reputation: 28703
Memcache explicitly does not provide a way to iterate over the keys in use. You can read or write based on a specific key, but you can not get a list of all keys or iterate over them. This is a limitation of memcache.
Unfortunately, a before_filter
won't work because sessions can be expired in memcached without your app being notified about it.
Why do you want to get this information?
Upvotes: 1
Reputation: 9093
I don't think you can do that with memcache.
Must admit I am yet to use MemCacheStore but you could probably implement something using before filters in the application controller with a cron job and a table in your database.
Upvotes: 0