[翻译]Why you don’t want to shard

本文探讨了在面对巨大workset和高频写入操作时采用分片(sharding)的必要性和策略。通过案例分析Facebook的增长挑战,介绍了几种常见的分片方法,包括按功能划分、按值哈希以及通过查询服务器实现分片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接
shard在某些情况下有道理,但是在很多情况下它只会让系统更加复杂。
所以对于系统而言,首先应该优化其它的东西,当此时performance还是不够好,或者说还是性能非常差,就需要猛药了,一般来说做shard可以归结为以下两个原因:

  • 巨大的workset:当经常访问的数据超过整个单机的缓存或者数据库单张表太过于巨大导致查询插入速度非常慢,就需要考虑用shard将整个workset进行shard。
  • 写太过于频繁:因为写速度太快导致服务器支撑不住,就需要将workset进行拆分到多台机器,加快写速度。当然这里的目的是将写能够平均分摊到多台机器上,如果做完shard之后还是让大部分写打到一台机器上,这样的shard是没有意义。
    我们以facebook为例,最开始facebook只是哈佛大学学生内部使用,数据存储量和访问量没那么大,而现在的facebook的140亿每个月,它的存储量是1P photo,这些photo的metadata有几个T那么大,这个时候是应该纵向扩展(将现在的机器升级到更好的机器)还是横向扩展(增加机器)。回过头来想,其实根本原因是响应速度太慢,用户没有办法接受,而这个问题基本上可以归结于上面两个原因,巨大的workset,一般来说我们是可以做cache,但是cache会有命中问题,当访问量很大,大到cache全部使用的情况下命中率也不高,这样响应速度就会比较慢。频繁的写,假设14bm,写估计有10分之1,也有1.4bm的写,这就考虑IO的速度了,无论如何提升,单机的IO访问速度肯定是有限的。综合上面两个原因分析,facebook无法通过更新服务器来支撑庞大的业务访问量,只能通过横向扩展,增加新的服务器。

如何做shard

要解决上面两个问题,有下面几个策略来做:

  • 按功能划分:通常情况这是最好的方法,找出系统的瓶颈,比如经常读写的table,将它们移到单独的机器上去,这样是最好的办法,功能隔离而且让系统结构简单,可以解决大部分策略。优先考虑这种策略。
  • 根据表的某个value来进行shard:某个表太过于巨大,将其拆分,选择某个column做hash,保证将数据平均分配到多台机器上。但是现实中,很难做对,因为很多时候请求都会打到某几个shard上,这几台机器会负载比较重,其它机器会比较轻松。比如按照邮编号来进行划分,比如北京访问量大,小城市访问量小,就会导致有些机器负载较重,有些很轻,还是让用户感觉系统反应比较慢。
  • 通过查询服务器来选择shard:一般是将需要shard的数据发给一个服务器由它来决定数据到哪个shard上,这个的好处是非常scalable,但是非常复杂。

为什么复杂?

复杂的原因主要归结于以下两个:
- 需要逻辑来处理sharding
- 维护成本很高,比如backup,增加index以及修改shard策略,修改schema
对于第2个原因深有感触,当要修改shard策略和需要格式发生变化,增加某个字段,那简直是噩梦,尤其要做到热重启,如果没有多个replica就根本做不到,但是replica的问题就是数据同步,当更新完某个replica之后还需要将数据进行更新,非常麻烦。

  • 合并表结果:facebook将photo和useinfo以及用户对photo的comment放在三个表中,按照shard之后将这三张表划分到三台机器上,以前只需要在一台机器中查询三个表就可以做合并,现在需要查询三台机器。一个通常的workaround就是增加数据的冗余,将comment和photo放在作为外键保存在useinfo中,当查询unserinfo可以将这些数据一起返回,这样就不需要查询其它两个数据库了,但是这里涉及的另外一个问题就是数据冗余带来的同步问题。
  • 查询:当按照某个field做的shard,查询的时候一般是不支持非这个Field的查询,因为它需要访问所有的数据库然后还要合并,这是一个非常耗时的操作。
  • reshard:当某个shard访问还是很大的时候,做reshard,要做到没有down机的shard是非常困难。更困难的是修改shard策略,数据就需要重新分布。
"failed to load then jni shard library jvm.dll" 这个错误通常在尝试运行Java应用程序时出现。它表示无法加载jvm.dll这个JNI共享库文件。以下是一些可能的解决方案: 首先,确保您正在使用的是正确版本的Java运行时环境(JRE)或Java开发工具包(JDK)。如果您安装了多个Java版本,请检查您的系统环境变量中的JAVA_HOME设置,并确保它指向正确的Java安装目录。 其次,检查您的系统是否正确设置了JAVA_HOME环境变量。如果没有,请手动设置它,指向正确的Java安装目录。 如果您尝试在64位系统上运行32位的Java程序,或者反之,可能会导致这个错误。请确保您正在使用与您的操作系统架构(32位或64位)相匹配的Java版本。 还有可能是由于损坏的Java安装文件导致的问题。在这种情况下,您可以尝试重新安装Java以修复这个错误。 另外,如果您正在使用Eclipse或其他IDE,请确保您的项目配置正确,包括指定了正确的JRE或JDK路径。 最后,如果您的计算机上没有安装Java,您可能需要下载并安装一个适当的Java版本。在安装过程中,请确保您选择正确的安装选项,以便安装所需的JNI库文件。 总之,"failed to load then jni shard library jvm.dll" 错误通常是由于Java环境配置问题引起的。通过检查您的Java安装、环境变量、系统架构以及IDE配置,您应该能够解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值