How Bilibili Rebuilt Its Account System with a Multi‑Tenant Microservice Architecture
This article explains how Bilibili's account platform was refactored into a unified multi‑tenant microservice system, covering the background problems, domain‑driven design, data isolation strategies, configuration‑driven tenant onboarding, deployment models, gray‑release migration, and solutions for bidirectional data sync loops.
Background
The original account system supported multiple business lines (domestic Bilibili, international Bilibili, overseas games) each with its own code branch, leading to high maintenance cost, knowledge silos, and painful API integration for upstream teams.
Account Architecture
The new design consolidates all business lines into a single codebase using a multi‑tenant approach, starting with the overseas game line. Core capabilities include authentication, user information management, and various user‑facing functions such as registration, login, password management, phone/email binding, and SNS management.
Key service domains are split into:
User domain : handles account registration and basic user data.
Authentication domain : manages login and token issuance.
Captcha domain : provides behavior verification.
Blacklist domain : manages phone number blacklists.
Email/SMS domain : handles verification messages.
Four‑Layer Service Model (DDD‑Inspired)
Interface layer : entry points (gRPC, HTTP, MQ, jobs) and message listeners.
Application layer : orchestrates processes such as login validation, token generation, and response handling.
Domain layer : implements business logic like token creation and persistence.
Infrastructure layer : adapters for external resources (MySQL, KV stores) abstracted from upper layers.
Multi‑Tenant Scheme
Each tenant (e.g., domestic Bilibili, international Bilibili, overseas games) represents an independent account system. Differences among tenants include:
Physical data isolation : separate databases or tables.
Business‑logic variations : e.g., domestic version supports Google login, international does not.
External dependency differences : different KV or MySQL resources per region.
To avoid scattered if‑else code, the system abstracts differing parts behind interfaces and selects implementations via tenant‑specific configuration.
Data Isolation Techniques
Database‑level isolation : each tenant uses a dedicated database (high security, suitable for high QPS).
Table‑level isolation : tenants share a database but use distinct tables (quick to provision, lower traffic).
Configuration‑Driven Tenant Onboarding
Tenant configuration is expressed as maps defining database, Redis, and service implementations. Adding a new tenant only requires updating the configuration file, regardless of whether the deployment is isolated or shared.
# db data source configuration
[db]
[db.intl]
addr = "172.0.0.1:5805"
dsn = "bstar:xxxxxxxxxxxx@tcp(172.0.0.1:5805)/intl"
active = 10
[db.main]
addr = "172.0.0.1:5062"
dsn = "main:xxxxxxxxxxxx@tcp(172.0.0.1:5062)/main"
active = 10
# redis data source configuration
[redis]
[redis.intl]
addr = "172.0.0.1:7101"
[redis.main]
addr = "172.0.0.1:7102"
# tenant configuration
[tenant]
defaultKey = "main"
[tenant.configs.main.domainService]
"TokenService" = "TokenServiceMain"
[tenant.configs.main.daoService]
"TokenPersistence" = "KvToken"
[tenant.configs.main.dao]
db = "main"
table = ""
redis = "main"
[tenant.configs.intl.domainService]
"TokenService" = "TokenServiceBstar"
[tenant.configs.intl.daoService]
"TokenPersistence" = "DbToken"
[tenant.configs.intl.dao]
db = "intl"
table = "intl"
redis = "intl"Deployment Models
Independent deployment : for high‑traffic, high‑availability tenants; resources are dedicated but code remains single.
Shared deployment : multiple low‑traffic tenants share the same resources; onboarding is done by adjusting configuration maps.
Gray‑Release Migration Strategy
The migration to the new multi‑tenant system follows five steps:
Routing : upstream services continue calling the old system while the old system routes requests based on whitelist or percentage for gray release.
Bidirectional sync : binlog‑based synchronization ensures near‑real‑time consistency between old and new databases, handling schema differences.
Loop prevention : added sync_time timestamps and Redis markers to detect and discard already‑processed changes, avoiding infinite update/insert/delete cycles.
Data verification : incremental binlog checks and dual‑query validation detect inconsistencies; mismatches trigger alerts for manual correction.
Future outlook : plan to replace Canal‑based sync with DTS once the internal data‑transfer service matures.
Conclusion
Refactoring the account system into a multi‑tenant microservice architecture reduced maintenance overhead, enabled unified code reuse across business lines, and provided a flexible, configurable way to onboard new tenants while ensuring safe, observable migration through comprehensive gray‑release and data‑sync mechanisms.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
dbaplus Community
Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
