Question: Design User System

For example: Twitter Login

User Case

  • Register/Update/Remove
  • Login/Logout
  • Balance/Membership

Necessary - Register

  • Current Total User: 100,000,000
  • Current Daily active users: 1,000,000
  • Predict
    • Daily active users in three months = 1,000,000*2 = 2,000,000
    • Register Percentage = 1%
    • Daily new register users = 2,000,000*1% = 20,000

Necessary - Login

  • Predict
    • Login percentage = 15%
    • Average login time = 1.2, concerning login failure/ login<-->logout
    • Daily login time = 2,000,000 * 15% * 1.2 = 360,000
    • Average Login Frequency = 360,000 / 24 hour = 1,800,000/24/60/60 = 4.2/s
    • Normal Login frequency = 4.2 * 2 8.4/s
    • Peak Login Frequency = 8.4 * 5 = 42/s

Application

Data - User(V1)

protocol User {
    private var userID: Int // Primary Key Int64
    private var name: String
    private var password: String
}

Data - User Tble(V1)

//column: UserID Name Password
protocol UserTable {
    private var table: Array<User>

    public func insert(...) -> ...
    public func delete(...) -> ...
    public func update(...) -> ...
    public func select(...) -> ...
}

Question: Support user management such as verification and ban

State Lifecycle Graph(V1)

New User -> Register action -> Active state -> Remove action

State Lifecycle Graph(V2)

  • User Verification - what if bot register user

New User -> Register Action -> Unverified State User -> Approve Action-> Active State User

New User -> Register Action -> Unverified State User -> Reject Action -> Delete/Waiting for timeout to Delete(will not add it into user system)

  • User Ban/Active - what if user/admin want to ban or make Account in private

Active State User -> Ban Action -> Banned state user (admin action)

Banned state User -> Unban action -> Active User (admin action)

Active User -> Deactivate state-> Inactive state (user action)

  • Remove

Unverified State User -> Reject Action -> Delete/Waiting for timeout to Delete(will not add it into user system)

Banned state User -> Remove action -> Delete/Fake Delete showing "User Canceled"

Inactive state User -> Remove action -> Delete/Fake Delete showing "User Canceled"

Data - User(V2)

protocol User {
    private var userID: Int // primary key Int64
    private var name: String // constant size
    private var hiddenPassword: String // constant size, one-way hashing with salts
    private var state: Int
}

Session

  • Session is a conversation between a user and a server
  • A user will have multiple sessions when user logins form different devices at the same time
  • You should as least remember your sessionID
  • Has service has session, even if does not login

Session LifeCycle graph(V1)

Offline state User -> Login action -> Online state user -> Logout state -> Offline user

Online state User -> timeout -> Offline state User

Data - User(V3)

protocol User {
    private var userID: Int // primary key Int64
    private var name: String // constant size
    private var hiddenPassword: String // constant size, one-way hashing with salts
    private var state: Int
    private var sessionList: Array<Session>
}

protocol Session {
    private var sessionID: Int
    private var userID: Int
    private var deviceCode: Int
    private var timeOut: Date
}

Problems: So separate UserTable/SessionTable

  • What if unlogin user? Generate 100W unnamed random user, once unlogin user addin, pair a random user to unlogin user
  • We update sessionList more frequently
  • The size of sessionList is dynamic

Data - UserTable and SessionTable(V4)

protocol User {
    private var userID: Int // primary key Int64
    private var name: String // constant size
    private var hiddenPassword: String // constant size, one-way hashing with salts
    private var state: Int
}

// column: UserID Name Password
protocol UserTable {
    private var table: Array<User>

    public func insert(...) -> ...
    public func delete(...) -> ...
    public func update(...) -> ...
    public func select(...) -> ...
}

protocol Session {
    private var sessionID: Int // primary key Int64
    private var userID: Int // Foreign Key
    private var deviceCode: Int
    private var timeOut: Date
}

// session table
protocol SessionTable {
    private var table: Array<Session>

    public func insert(...) -> ...
    public func delete(...) -> ...
    public func update(...) -> ...
    public func select(...) -> ...
}

Question: How to implement remember me

  • Setting the timeout in Session

Question: How optimize SessionTable

  • save SessionTable in Memory. Even if memory loses all, just re-login
  • no need to check the timeout frequenly.
    • When the user login, first check whether the session is expired. If so, update timeout.
    • Or delete timeout session once per day

Question: Query userID = 11?

  • index with hash O(1): add - private var hashValue:Int

Question: Range query userID < 30?

  • Index with Binary Search Tree,
    • space O(n)
    • insert O(lg2N)
    • delete O(lg2N)
    • lookup O(lg2N)
    • range query O(lg2(N+K)), binary search find, then inorder traversal
  • B+Tree,
    • space O(n)
    • insert O(lgbN)
    • delete O(lgbN)
    • lookup O(lgbN)
    • query O(lognb(N+K))
    • Advantages: disk friendly with continuous reading

Question: Payment with membership

class Membership {
    private var userID: Int
    private var money: Double
    private var expirationTime: Date

    public func addMoney(...) -> ...
    public func buyMmeber(...) -> ...
}

Problems

  • data inconsistence, system down after money paid, before expirationTime add
    • Solution: add transaction with log. Wite log first then perform operation
  • dup Member with the same userID / shadow User, userID not valid
    • add checker
typealias CheckFunction = ()->()
class Checker {
    private var checkList: Array<CheckFunction>
    public func register(checkFunction: CheckFunction) -> Bool
}

Checker checker;
checker.register(checkUnknownUser)
checker.register(checkDuplicatedUser)
  • user buy seversal times shortly
    • thread-safe problem
    • lock when transaction processing

ACID Principle ~ too strict

  • Atomicity - all or nothing
  • Consistency, valid according to all defined rules
  • Isolation, a kind of independency between transactions
  • Durability, stored permanently

Question: Design PayPal

start from Scenario

  • send/reveive
  • add money/ get cash
  • transfer/payment

AddMoney

  • calculate QPS
  • addMoney LifeCycle Graph

New Order -> Verification -> success/fail

  • data structure
    • UserTable
    • OrderTable
protocol User {
    private var userID: Int
}

protocol Account {
    private var accountID: Int
    private var userID: Int
    private var bankID: Int
    private var routingNumber: String
    private var dayLimit: Int
}

protocol Order {
    private var orderID: Int // primary Key
    private var userID: Int // foreign Key
    private var accountID: Int
    private var amount: Int
    private var operation: Int
    private var state: Int
    private var createTime: Date
    private var expirationTime: Date
}

Question: If succeed, process?

  • log at first, view of dataflow
  • lock transaction -> log -> load user data -> update -> unlock transaction -> submit -> notification

results matching ""

    No results matching ""