Question

Codry on Sun, 03 Jan 2016 23:36:24


Hi,

i have a simple community and now i want to cache a object with user information. Let say i have this:

public class UserModel {
    public User User {get; set; }
    public List<Post> Posts {get; set; }
}

public class User {
    public string UserName {get; set;}
    public int UserId {get; set;}
    public string Email {get; set;}
}

public class Post {
    public string Header {get; set;}
    public int PostId {get; set;}
    public DateTime CreateDate {get; set;}
}

When the profile page is loading i want to use the username(or the userid) to recive the information.

Today i use Azure Sql, but i want to use a faster way to get this information. Is the best way to use Redis or a NoSql solution(Cassandra, Couchbase...) or maybe Elastic Search/Solr? If i can search on the username it will be perfect.

What is best to use on Azure? Performance vs cost? My budget is ~$130 / month



Sponsored



Replies

Nagamalar Nagarajan on Mon, 04 Jan 2016 11:41:32


Hi,

You requirement would decide the best option for you.
You could get details about Redis Cache, and NoSQL in the links below:
https://azure.microsoft.com/en-in/documentation/articles/cache-dotnet-how-to-use-azure-redis-cache/
https://azure.microsoft.com/en-in/documentation/articles/fundamentals-data-management-nosql-chappell/

Regards,
Malar

Chourouk Hjaiej on Mon, 04 Jan 2016 12:55:05


Hello my friend, 

Please take a look on this link, you will unferstand the Redis Cache :) 

https://code.msdn.microsoft.com/Build-your-app-with-Azure-3b4e702d

Best of luck :)

Codry on Mon, 04 Jan 2016 15:42:51


Thanks for the information.

I have used both redis and elastic search before. But i dont know which is the best to use to cache models?
Redis is simple but is expensive and has limitations. I think is hard to search for users in redis? Elastic search is perfect when i need to search for users, but for cache? And NoSql, how simple is it to store/cache models in NoSql?

HSUlriksen on Thu, 28 Apr 2016 09:54:52


Hi,

this can fit both in DocumentDB, Redis and Azure Search (elastic). I think your access pattern may be the deciding factor as well together with cost. I assume you will access by user ID and that you will need the post paged by date. 

Redis

Remember that Redis is an in memory service unless you go for the Permium offering which starts at $413 per month. So, unless you have another persistent store this may not be what you're looking for.  

If you use SQL as a persistent store, I suggest using Redis as a normal cache aside implementation . You may utilize the Redis datastructures to make a bit more advanced cache aside, but the main point is that you will ask the cache, if does not have the data you need the client will fetch those data from SQL and update redis. Next time those data will be available in Redis. I have made an open source cache a side implementation myself, available as nuget and GitHub.

If you have Redis with persistent storage you can implement this a few different ways. Here's one, it will allow you to retrieve user data and posts, either the whole set or N numbers based on a sort. In this example I suggest using post data for sorting.

  • Hashset for user data called users, use the userId or name as member (depends on how you access those data) and then either serialize the user data or just store the email in value. Depends on how much info you need per user. Note that binaryformatter is slow (although it accepts nearly everything) so manual serialization or something like JIL (fast json, human readable) or MessagePack (fast binary, not human friendly) may a better serializer for you.
  • Hashset per user called posts:{userName or Id}. Having postId as members with serialized post data as value.
  • Sorted set per user called posts:sort:{userName or Id, same as above} which use the post date in epoch format as score, and the post id as member. 

To query the data you can use a Lua script which returs user info, and a set of posts. Something in the line of 

local userId = KEYS[1]
local fromPost = ARGV[1]

local userInfo = redis.call('HGET', 'users', userId)

local pagedPostsId = redis.call('ZREVRANGE', 'posts:sort:' .. userId, fromPost, 50) 

local posts = redis.call('HMGET', 'posts:' .. userId, unpack(pagedPostsId))

return {userInfo, posts }

Code is not tested, just from memory. If you use stackexchange.redis I suggest using named variables instead of KEYS / ARGV. Using 0 as argument for fromPost will return the 50 latest posts. 

I highly recommend reading the introduction to redis datatypes http://redis.io/topics/data-types-intro

Azure DocumentDB

Azure DocumentDB is a cloud scale documentDB and for a simple community you should be able to get away with the lowest pricing option of one single partition. It will set you back about $24 per month. 

DocumentDB works by persisting your objects as JSON and you can then retrieve them by querying in a SQL dialect. What you need to think about here is the data modelling, which differs a bit from SQL. As posts are unbounded and updated at different times I think you could have one document for the user and then a document per post. There may be reasons to aggregate som of the post data up to the user document such as number of posts, I suggest a video from this years Build conference for modeling tips. https://channel9.msdn.com/Events/Build/2016/P468

Sorting in DocumentDB is a bit different than SQL, so you will need to serialize your date as epoch, see https://azure.microsoft.com/en-us/blog/working-with-dates-in-azure-documentdb-4/

Retrieving your posts is then as easy as a SELECT * FROM posts p WHERE p.userId = 'someuser' ORDERBY p.CreateDate. The video from build will also show you how you can retrieve user data and post data with one query. 

Conclusion

So, we now got 3 different solutions:

1. Redis as a cache a side with SQL as a backing store. Minimal change from todays storage, but you pay for both Redis and SQL. Your queries will be "slow"/hit SQL when data is not in Redis.

2. Persistent Redis storage. Expensive but fun. 

3. DocumentDB. Easy, but you will need to look at your data modelling.

My recommendation would be to start out with DocumentDB, it's fast and I believe it will be your cheapest option for now. It is also scalable should you have massive amounts of traffic. 

Hope this helps.

Codry on Tue, 10 May 2016 20:47:51


Perfect. Thanx for a great answer.

I try Redis. I Create keys like user:id:{UserId}:name:{UserName}. Then i can find the cache for the user with the userid or the username. Is that the "right way" to go? :)