Data Engineer Case Study 面试:多租户数据隔离方案(Snowflake/Cloud 真题)
data-engineersystem-designcase-studyinterviewarchitecture

Data Engineer Case Study 面试:多租户数据隔离方案(Snowflake/Cloud 真题)

本文基于真实候选人面经整理Data面试全流程。还原面试题目、解题思路与技术考察重点,覆盖Snowflake、Azure、系统设计、System Design,附详细准备策略助你高效备战。

Sam · · 12 分钟阅读

面试真题来源:Snowflake/Cloud Data Engineer 系统设计面试
难度:Hard | 考察领域:System Design / Architecture
核心考点:多租户、数据隔离、权限管理、资源隔离

面试场景

这是 Snowflake/Cloud DE 面试中非常经典的一道 Case Study 题:

题目:设计一个支持多租户数据隔离的平台

面试官通常会给你一个真实的业务场景,要求你设计完整的数据处理架构。这道题考察的是你对多租户、数据隔离、权限管理、资源隔离的全面理解。

业务需求分析

核心业务场景

在 Snowflake/Cloud 这样的平台,多租户数据隔离需要支持:

  1. 数据隔离:租户之间数据完全隔离
  2. 权限管理:细粒度权限控制
  3. 资源隔离:计算资源隔离,避免互相影响
  4. 审计日志:操作审计和合规要求

关键约束条件

  • 租户数量:数百到数千租户
  • 数据量:每个租户 TB 级数据
  • 隔离级别:强隔离(物理隔离)或弱隔离(逻辑隔离)
  • 合规要求:GDPR、HIPAA 等数据合规

整体架构设计

┌─────────────────────────────────────────────────────────────────┐
│                         Tenant Layer                            │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │
│  │  Tenant A   │  │  Tenant B   │  │  Tenant C   │             │
│  │  (数据+资源)  │  │  (数据+资源)  │  │  (数据+资源)  │             │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘             │
└─────────┼────────────────┼────────────────┼─────────────────────┘
          │                │                │
          ▼                ▼                ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Isolation Layer                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │
│  │  Data       │  │  Resource   │  │  Permission │             │
│  │  Isolation  │  │  Isolation  │  │  Management │             │
│  └─────────────┘  └─────────────┘  └─────────────┘             │
└─────────────────────────────────────────────────────────────────┘
          │                │                │
          ▼                ▼                ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Storage Layer                               │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │
│  │  S3/        │  │  ADLS/      │  │  HDFS       │             │
│  │  GCS        │  │  Azure Blob │  │  (Hadoop)   │             │
│  └─────────────┘  └─────────────┘  └─────────────┘             │
└─────────────────────────────────────────────────────────────────┘
          │                │                │
          ▼                ▼                ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Compute Layer                               │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │
│  │  Spark      │  │  Flink      │  │  Databricks │             │
│  │  (计算引擎)   │  │  (流处理)   │  │  (统一管理)  │             │
│  └─────────────┘  └─────────────┘  └─────────────┘             │
└─────────────────────────────────────────────────────────────────┘

详细设计方案

1. 数据隔离策略

隔离级别

  • 强隔离:物理隔离,独立存储和计算资源
  • 弱隔离:逻辑隔离,共享存储和计算资源
  • 混合隔离:核心数据物理隔离,非核心数据逻辑隔离

实现方案

# 强隔离:独立 Schema/Database
class StrongIsolation:
    def __init__(self, tenant_id):
        self.tenant_id = tenant_id
        self.schema_name = f"tenant_{tenant_id}"
    
    def create_schema(self, spark):
        spark.sql(f"CREATE SCHEMA IF NOT EXISTS {self.schema_name}")
    
    def create_table(self, spark, table_name, schema):
        spark.sql(f"""
            CREATE TABLE IF NOT EXISTS {self.schema_name}.{table_name} 
            USING DELTA
            TBLPROPERTIES ('delta.logRetentionDuration' = 'interval 30 days')
        """)
    
    def query(self, spark, table_name):
        return spark.table(f"{self.schema_name}.{table_name}")

# 弱隔离:tenant_id 列
class WeakIsolation:
    def __init__(self, tenant_id):
        self.tenant_id = tenant_id
    
    def query(self, spark, table_name):
        from pyspark.sql.functions import col
        return spark.table(table_name).filter(col("tenant_id") == self.tenant_id)

2. 资源隔离

资源配额

  • 计算资源:CPU、内存、并行度
  • 存储资源:存储空间、IO 带宽
  • 网络资源:网络带宽、连接数

资源管理

# 资源隔离示例
from pyspark.sql import SparkSession

class ResourceIsolation:
    def __init__(self, tenant_id, quota):
        self.tenant_id = tenant_id
        self.quota = quota
    
    def create_spark_session(self):
        spark = SparkSession.builder \
            .appName(f"tenant_{self.tenant_id}") \
            .config("spark.executor.cores", self.quota.get("cpu", 4)) \
            .config("spark.executor.memory", self.quota.get("memory", "4g")) \
            .config("spark.sql.shuffle.partitions", self.quota.get("shuffle_partitions", 200)) \
            .getOrCreate()
        
        return spark
    
    def set_resource_limits(self, spark):
        # 设置资源限制
        spark.conf.set("spark.sql.execution.maxBroadcastTableSize", 
                       self.quota.get("broadcast_size", 1024 * 1024 * 1024))
        spark.conf.set("spark.sql.files.maxPartitionBytes", 
                       self.quota.get("partition_size", 128 * 1024 * 1024))

3. 权限管理

权限模型

  • RBAC:基于角色的访问控制
  • ABAC:基于属性的访问控制
  • ABAC+RBAC:混合权限模型

权限配置

# 权限配置示例
permissions:
  tenant_admin:
    - read
    - write
    - delete
    - admin
  tenant_user:
    - read
    - write
  tenant_viewer:
    - read
  data_scientist:
    - read
    - execute
  data_engineer:
    - read
    - write
    - execute

权限实现

# 权限管理示例
from functools import wraps

class PermissionManager:
    def __init__(self):
        self.permissions = {}
    
    def set_permission(self, role, permissions):
        self.permissions[role] = permissions
    
    def check_permission(self, role, action):
        role_permissions = self.permissions.get(role, [])
        return action in role_permissions
    
    def require_permission(self, action):
        def decorator(func):
            @wraps(func)
            def wrapper(user_role, *args, **kwargs):
                if not self.check_permission(user_role, action):
                    raise PermissionError(f"User role {user_role} does not have {action} permission")
                return func(*args, **kwargs)
            return wrapper
        return decorator

# 使用示例
pm = PermissionManager()
pm.set_permission("tenant_admin", ["read", "write", "delete", "admin"])
pm.set_permission("tenant_user", ["read", "write"])

@pm.require_permission("write")
def write_data(user_role, data):
    # 写入数据逻辑
    pass

4. 审计日志

审计内容

  • 操作日志:谁在什么时候做了什么操作
  • 数据访问:谁访问了哪些数据
  • 资源使用:资源使用情况

审计实现

# 审计日志示例
import json
from datetime import datetime
from functools import wraps

class AuditLogger:
    def __init__(self):
        self.logs = []
    
    def log(self, user_id, action, resource, details=None):
        log_entry = {
            "timestamp": datetime.now().isoformat(),
            "user_id": user_id,
            "action": action,
            "resource": resource,
            "details": details or {}
        }
        self.logs.append(log_entry)
        # 发送到审计日志系统
        self.send_to_audit_system(log_entry)
    
    def send_to_audit_system(self, log_entry):
        # 发送到 Kafka/CloudWatch/其他审计系统
        pass
    
    @staticmethod
    def audit_action(action):
        def decorator(func):
            @wraps(func)
            def wrapper(self, user_id, *args, **kwargs):
                result = func(self, *args, **kwargs)
                self.logger.log(
                    user_id=user_id,
                    action=action,
                    resource=func.__name__,
                    details={"args": str(args), "kwargs": str(kwargs)}
                )
                return result
            return wrapper
        return decorator

# 使用示例
class DataService:
    def __init__(self):
        self.logger = AuditLogger()
    
    @AuditLogger.audit_action("CREATE_TABLE")
    def create_table(self, user_id, table_name, schema):
        # 创建表逻辑
        pass
    
    @AuditLogger.audit_action("QUERY_DATA")
    def query_data(self, user_id, table_name, conditions):
        # 查询数据逻辑
        pass

关键技术决策

为什么选择这个方案?

  1. 强隔离:物理隔离保证数据安全
  2. 细粒度权限:RBAC 权限模型
  3. 资源隔离:避免租户互相影响
  4. 审计合规:满足合规要求

技术选型对比

方案优势劣势适用场景
强隔离数据安全成本高高安全要求
弱隔离成本低安全风险低风险场景
RBAC简单易用灵活性差标准权限
ABAC灵活定制复杂度高复杂权限

面试官追问

常见追问问题

  1. 如果租户数量增加 10 倍,架构如何调整?

    • 增加存储节点
    • 优化资源分配
    • 增加权限管理复杂度
  2. 如果要求跨租户数据共享,如何实现?

    • 数据视图:共享数据视图
    • 数据同步:跨租户数据同步
    • 权限控制:细粒度权限控制
  3. 如果某个组件宕机,如何保证系统可用性?

    • 多节点部署
    • 故障转移机制
    • 数据备份和恢复

面试技巧

回答框架

  1. 澄清需求:明确业务场景和技术约束
  2. 架构设计:画出架构图,说明每个组件的职责
  3. 技术选型:解释为什么选择某个技术
  4. 权衡分析:讨论方案的优缺点

高分回答要点

  • 租户数量:数百到数千租户
  • 隔离级别:强隔离或弱隔离
  • 权限管理:RBAC 权限模型
  • 审计合规:满足合规要求

本文整理自真实 Data Engineer 面试经验,架构设计经过实际验证。


💡 需要面试辅导?

如果你对准备技术面试感到迷茫,或者想要个性化的面试指导和简历优化,欢迎联系 Interview Coach Pro 获取一对一辅导服务。

👉 联系我们 获取专属面试准备方案

准备好拿下下一次面试了吗?

获取针对你的目标岗位和公司的个性化辅导方案。

联系我们