Heim> Schlagzeilen> Hauptteil

ceph对象存储一定要在上线前摸清楚

-
Freigeben: 2018-03-12 09:14:14
Original
3768 Leute haben es durchsucht

Ceph作为一款开源的分布式存储软件,可以利用X86服务器自身的本地存储资源,创建一个或多个存储资源池,并基于资源池对用户提供统一存储服务,包括块存储、对象存储、文件存储,满足企业对存储高可靠性、高性能、高可扩展性方面的需求,并越来越受到企业的青睐。经过大量的生产实践证明,Ceph的设计理念先进,功能全面,使用灵活,富有弹性。不过,Ceph的这些优点对企业来说也是一把双刃剑,驾驭的好可以很好地服务于企业,倘若功力不够,没有摸清Ceph的脾性,有时也会制造不小的麻烦,下面我要给大家分享的正是这样的一个案例。

1.jpg

A公司通过部署Ceph对象存储集群,对外提供云存储服务,提供SDK帮助客户快速实现对图片、视频、apk安装包等非结构化数据的云化管理。在业务正式上线前,曾经对Ceph做过充分的功能测试、异常测试和性能测试。

集群规模不是很大,使用的是社区0.80版本,总共有30台服务器,每台服务器配置32GB内存,10块4T的SATA盘和1块160G的Intel S3700 SSD盘。300块SATA盘组成一个数据资源池(缺省配置情况下就是名称为.rgw.buckets的pool),存放对象数据;30块SSD盘组成一个元数据资源池(缺省配置情况下就是名称为.rgw.buckets.index的pool),存放对象元数据。有过Ceph对象存储运维部署经验的朋友都知道,这样的配置也算是国际惯例,因为Ceph对象存储支持多租户,多个用户在往同一个bucket(用户的一个逻辑空间)中PUT对象的时候,会向bucket索引对象中写入对象的元数据,由于是共享同一个bucket索引对象,访问时需要对这个索引对象加锁,将bucket索引对象存放到高性能盘SSD组成的资源池中,减少每一次索引对象访问的时间,提升IO性能,提高对象存储的整体并发量。

系统上线后,客户数据开始源源不断地存入到Ceph对象存储集群,在前面的三个月中,一切运行正常。期间也出现过SATA磁盘故障,依靠Ceph自身的故障检测、修复机制轻松搞定,运维的兄弟感觉很轻松。进入到5月份,运维兄弟偶尔抱怨说SSD盘对应的OSD有时会变的很慢,导致业务卡顿,遇到这种情况他们简单有效的办法就是重新启动这个OSD,又能恢复正常。大概这种现象零星发生过几次,运维兄弟询问是不是我们在SSD的使用上有什么不对。我们分析后觉得SSD盘的应用没有什么特别的地方,除了将磁盘调度算法修改成deadline,这个已经修改过了,也就没有太在意这个事情。

5月28日晚上21:30,运维兄弟手机上接到系统告警,少部分文件写入失败,马上登陆系统检查,发现是因为一台服务器上的SSD盘对应的OSD读写缓慢引起的。按照之前的经验,此类情况重启OSD进程后就能恢复正常,毫不犹豫地重新启动该OSD进程,等待系统恢复正常。但是这一次,SSD的OSD进程启动过程非常缓慢,并引发同台服务器上的SATA盘OSD进程卡顿,心跳丢失,一段时间后,又发现其它服务器上开始出现SSD盘OSD进程卡顿缓慢。继续重启其它服务器上SSD盘对应的OSD进程,出现了类似情况,这样反复多次重启SSD盘OSD进程后,起不来的SSD盘OSD进程越来越多。运维兄弟立即将此情况反馈给技术研发部门,要求火速前往支援。

到办公室后,根据运维兄弟的反馈,我们登上服务器,试着启动几个SSD盘对应的OSD进程,反复观察比对进程的启动过程:

1、 用top命令发现这个OSD进程启动后就开始疯狂分配内存,高达20GB甚至有时达到30GB;有时因系统内存耗尽,开始使用swap交换分区;有时即使最后进程被成功拉起,但OSD任然占用高达10GB的内存。

2、 查看OSD的日志,发现进入FileJournal::_open阶段后就停止了日志输出。经过很长时间(30分钟以上)后才输出进入load_pg阶段;进入load_pg阶段后,再次经历漫长的等待,虽然load_pg完成,但进程仍然自杀退出。

3、 在上述漫长启动过程中,用pstack查看进程调用栈信息,FileJournal::_open阶段看到的调用栈是在做OSD日志回放,事务处理中是执行levelDB的记录删除;在load_pg阶段看到的调用栈信息是在利用levelDB的日志修复levelDB文件。

4、 有时候一个SSD盘OSD进程启动成功,运行一段时间后会导致另外的SSD盘OSD进程异常死掉。

从这些现象来看,都是跟levelDB有关系,内存大量分配是不是跟这个有关系呢?进一步查看levelDB相关的代码后发现,在一个事务处理中使用levelDB迭代器,迭代器访问记录过程中会不断分配内存,直到迭代器使用完才会释放全部内存。从这一点上看,如果迭代器访问的记录数非常大,就会在迭代过程中分配大量的内存。根据这一点,我们查看bucket中的对象数,发现有几个bucket中的对象数量达到了2000万、3000万、5000万,而且这几个大的bucket索引对象存储位置刚好就是出现问题的那几个SSD盘OSD。内存大量消耗的原因应该是找到了,这是一个重大突破,此时已是30日21:00,这两天已经有用户开始电话投诉,兄弟们都倍感“鸭梨山大”。已经持续奋战近48小时,兄弟们眼睛都红肿了,必须停下来休息,否则会有兄弟倒在黎明前。

31日8:30,兄弟们再次投入战斗。

还有一个问题,就是有些OSD在经历漫长启动过程,最终在load_pg完成后仍然自杀退出。通过走读ceph代码,确认是有些线程因长时间没有被调度(可能是因levelDB的线程长时间占用了CPU导致)而超时自杀所致。在ceph的配置中有一个filestore_op_thread_suicide_timeout参数,通过测试验证,将这个参数设置成一个很大的值,可以避免这种自杀。又看到了一点点曙光,时钟指向12:30。

有些进程起来后,仍然会占用高达10GB的内存,这个问题不解决,即使SSD盘OSD拉起来了,同台服务器上的其它SATA盘OSD运行因内存不足都要受到影响。兄弟们再接再厉啊,这是黎明前的黑暗,一定要挺过去。有人查资料,有人看代码,终于在14:30从ceph资料文档查到一个强制释放内存的命令:ceph tell osd.* heap release,可以在进程启动后执行此命令释放OSD进程占用的过多内存。大家都格外兴奋,立即测试验证,果然有效。

一个SSD盘OSD起来后运行一会导致其它SSD盘OSD进程退出,综合上面的分析定位,这主要是因为发生数据迁移,有数据迁出的OSD,在数据迁出后会删除相关记录信息,触发levelDB删除对象元数据记录,一旦遇到一个超大的bucket索引对象,levelDB使用迭代器遍历对象的元数据记录,就会导致过度内存消耗,从而导致服务器上的OSD进程异常。

根据上述分析,经过近2个小时的反复讨论论证,我们制定了如下应急措施:

1、 给集群设置noout标志,不允许做PG迁移,因为一旦出现PG迁移,有PG迁出的OSD,就会在PG迁出后删除PG中的对象数据,触发levelDB删除对象元数据记录,遇到PG中有一个超大的bucket索引对象就会因迭代器遍历元数据记录而消耗大量内存。

2、 为了能救活SSD对应的OSD,尽快恢复系统,在启动SSD对应的OSD进程时,附加启动参数filestore_op_thread_suicide_timeout,设置一个很大的值。由于故障OSD拉起时,LevelDB的一系列处理会抢占CPU,导致线程调度阻塞,在Ceph中有线程死锁检测机制,超过这个参数配置的时间线程仍然没有被调度,就判定为线程死锁。为了避免因线程死锁导致将进程自杀,需要设置这个参数。

3、 在目前内存有限的情况下,异常的OSD启动会使用swap交换分区,为了加快OSD进程启动,将swap分区调整到SSD盘上。

4、 启动一个定时任务,定时执行命令ceph tell osd.* heap release,强制释放OSD占用的内存。

5、 SSD对应的OSD出现问题的时候,按如下步骤处理:

a) 先将该服务器上的所有OSD进程都停掉,以腾出全部内存。

b) 然后启动OSD进程,并携带filestore_op_thread_suicide_timeout参数,给一个很大的值,如72000。

c) 观察OSD的启动过程,一旦load_pgs执行完毕,可以立即手动执行ceph tell osd.N heap release命令,将其占用的内存强制释放。

d) 观察集群状态,当所有PG的状态都恢复正常时,再将其他SATA盘对应的OSD进程启动起来。

按照上述步骤,我们从17:30开始逐个恢复OSD进程,在恢复过程中,那几个超大bucket索引对象在做backfilling的时候需要较长时间,在此期间访问这个bucket的请求都被阻塞,导致应用业务请求出现超时,这也是单bucket存储大量对象带来的负面影响。

5月31日23:00,终于恢复了全部OSD进程,从故障到系统全部成功恢复,我们惊心动魄奋战了72小时,大家相视而笑,兴奋过度,再接再厉,一起讨论制定彻底解决此问题的方案:

1、 扩大服务器内存到64GB。

2、 对新建bucket,限制存储对象的最大数量。

3、 Ceph 0.94版本经过充分测试后,升级到0.94版本,解决单bucket索引对象过大问题。

4、 优化Ceph对levelDB迭代器的使用,在一个大的事务中,通过分段迭代,一个迭代器在完成一定数量的记录遍历后,记录其当前迭代位置,将其释放,再重新创建一个新的迭代器,从上次迭代的位置开始继续遍历,如此可以控制迭代器的内存使用量。

前事不忘后事之师,汲取经验教训,我们总结如下几点:

1、 系统上线前必须经过充分的测试

A公司的系统上线前,虽然对ceph做了充分的功能、性能、异常测试,但却没有大量数据的压力测试,如果之前单bucket灌入了几千万对象测试,也许就能提前发现这个隐患。

2、 运维过程中的每一个异常都要及时引起重视

此案例中,在问题爆发前一段时间,运维部门已经有反馈SSD异常的问题,可惜没有引起我们重视,倘若当时就深入分析,也许可以找到问题根由,提前制定规避措施。

3、 摸清ceph的脾性

任何软件产品都有相应的规格限制,ceph也不例外。如果能提前深入了解ceph架构及其实现原理,了解单bucket过度存放大量对象所带来的负面影响,提前规划,也不会出现本案例中遇到的问题。RGW对配额的支持非常全面,包括用户级别的、bucket级别的,都可以配置单个bucket允许存放的最大对象数量。

4、 时刻跟踪社区最新进展

在Ceph的0.94版本中,已经支持了bucket索引对象的shard功能,一个bucket索引对象可以分成多个shard对象存储,可有效缓解单bucket索引对象过大问题。

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!