瞎扯淡 关于数据库部份表做中英版本的探讨

breeze · 2018年04月22日 · 最后由 breeze 回复于 2018年04月25日 · 1359 次阅读

欢迎大家来指出不好的地方

产品需求分析

  1. 用户账号体系不分中英文版本:在中文版本下注册的用户,在英文版本中也可以登录。
  2. 资讯类的数据做中英文两个版本:在中文版本中只有中文资讯,英文版本下只有英文资讯。

解决思路

  1. 一个数据库,用户表不分中英两张表。资讯类的表分中英两张表。
  2. 部署两个 rails 服务 (中英各一个),在 initialization 中使 model table_name 映射到相应版本的表名。
  3. 通过 Nginx 根据自定义的 http 头识别中英版本的请求,转发到相应的 rails 服务。

具体代码

  1. 例如创建两个版本的帖子表:cn_topics 与 en_topics
  2. 创建一个名为 Topic 的 Model
  3. 在 config/initializers 中 创建 map_multiversion_models.rb
MULTIVERSION_MODELS = %w(Topic).freeze

if ENV['CURRENT_LANG'] === 'CN'
  current_lang_prefix = 'cn'
else
  current_lang_prefix = 'en'
end

MULTIVERSION_MODELS.each do |t|
  t.safe_constantize.table_name = "#{current_lang_prefix}#{t.underscore.pluralize}"
end
  1. nginx 的转发配置
upstream cn_production {
  server 192.168.1.11:3000;
}

upstream en_production {
  server 192.168.1.12:3000;
}

server {
  location / {
    if ($http_x_current_lang = 'cn') {
      proxy_pass http://cn_production;
      break;
    }

    if ($http_x_current_lang != 'cn') {
      proxy_pass http://en_production;
      break;
    }
  }
}

方案分析

  1. 数据隔离上通常有三种做法:数据库隔离、表隔离、元数据隔离。
    • 数据库实例隔离不符合业务需求
    • 元数据隔离方案会对正常业务代码造成污染,增加 lang 的字段来区别。
  2. 采用表隔离的方式,并用上面的解决方案
    • 可以按正常的逻辑去写业务代码,避免了因为中英文版本问题对代码做兼容处理。
    • 只需在环境变量中指定当前语言版本,即可同一套测试代码测试指定语言版本的业务代码

用一个标记字段区分就行了。

hooopo 回复

我这样理解对吗?

业务需求比较简单的情况下。使用元数据隔离 (维护多一个字段) 比表隔离 (维护两张表) 要更方便些。

具体的解决思路改成:

  1. 一个数据库,资讯类的表加一个标记字段 (lang)。
  2. 部署两个 rails 服务 (中英各一个),在 initialization 中使 model 的 default_scope 对应中英文版本
  3. 通过 Nginx 根据自定义的 http 头识别中英版本的请求,转发到相应的 rails 服务。

如果想区分国内外两套服务,用户名要全局惟一好还是两套各自惟一好

按照语言分表实际上有现成 gem: globalize

ericguo 回复

谢谢回复。 我去学习下该 gem

需要 登录 后方可回复, 如果你还没有账号请 注册新账号