User System

Senario

Request types: User register, user login, user query, user info update.
Assume DAU is 100 million.

User register, user login, and user info update altogether: 0.5/user/day, QPS ~100
User query: 100/user/day, QPS~100,000

Service

User service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
User getUser() {
key = userId + salt;
user = cache.get(key);
if (user)
return user;
user = database.get(userId); // mark
cache.set(key, user);
return user;
}
User setUser(User user) {
key = user.id + salt;
cache.delete(key); // order matters here
database.set(user);
}

Which implementation is better?
A. cache.delete(key); database.set(user);
B. database.set(user); cache.delete(key);
C. cache.set(key); database.set(user);
D. database.set(user); cache.set(key);

A, because B,C,D will easily cause data corruption(mismatch) in case of one operation falls. Case A usually does not cause dirty data, unless setUser() was invoked after the marked place in getUser(), which causes an older version of user been stored in cache.

To avoid the inconsistency issues, which may occur here and there in a concurrent system, we should set a cache timeout, so we can make sure that all data will eventually be the same.

Authentication service

After a user logged in:

  1. The server creates a session table(session_key, user_id, expire_time)
  2. Return session_key as cookie
  3. User browser stores the session_key
  4. Every request the user sent will take along with it all cookies from this site(so don’t make too many cookies)
  5. If the server sees the session_key in the cookie is effective, log in the user

Where should we put the sessions? cache? database?
Both. In case we lost all session tables in cache, a great number of users will try to log in at the same time, causing problems.

Friendship service

One-way or two-way. Usually in NoSQL database as it’s simple.

Storgae

  1. SQL: ~1k QPS
  2. NoSQL: ~10k QPS
  3. In-memory NoSQL(Redis / Memcached): ~100k QPS