写在前面
可能有部分使用过Oceanbase数据库的用户,对OceanBase的磁盘数据文件样式会提出这样的问题:为什么储存数据的只有一个大的block_file文件?
如果你平时有使用MySQL的习惯,那么对于OceanBase的磁盘文件势必会有这样的疑问。简单解析下,OceanBase是通过Linux系统调用fallocate函数的方式来“霸占”磁盘空间的。这种预分配方式的好处是可以保证占有一段尽可能连续的磁盘空间,避免其他应用程序对磁盘的抢占引起的磁盘资源不足,并且可以在其之上定制文件系统,提高数据访问效率。但你可能会吐槽此举会引发磁盘空间的浪费,例如一次占用很大的空间,即便磁盘空间不会被使用,也不能被释放。或者reboot不起来,原因是没有足够的磁盘空间来分配这个大文件。
针对预分配大块磁盘空间但不能被释放的问题,我们增加一种渐进磁盘扩容的用户配置选项,即预分配一个合理的磁盘大小,根据磁盘的实际使用情况自动扩容。这种方式的好处是不需要对磁盘预分配空间进行“一刀切”,而是让磁盘数据文件能根据业务实际使用,自动感知并扩容,简化操作。
做“刚刚好”的扩容
简单来说就是渐进式使用磁盘空间,灵活配置,告别简单粗暴的“一次性消费行为”。随时根据业务需要,手动调整扩容步长,让扩容更丝滑。
例如,有的业务可能需要使用1TB的磁盘空间,那么可以先设置1TB的空间,再设置能接受的最大上限,假设10TB,可能最终业务使用了5TB的空间,那么对于业务而言,并不需要一开始就设置10TB的空间,从而节省了5TB的磁盘成本开销。如果某一天业务的写入减少,对磁盘的需求增速降低的情况下,业务还可以降低每次自动扩容的大小,最大限度的降低对磁盘的分配,做“刚刚好”的系统。
当然,如果要启用磁盘数据文件自动扩容的功能,需要了解以下几个配置项的配合使用:
- datafile_size 磁盘数据文件占用磁盘可用空间大小。
- datafile_disk_percentage 磁盘数据文件占用磁盘可用空间的比例。
- datafile_next 磁盘数据文件自动扩容的步长。
- datafile_maxsize 磁盘数据文件自动扩容的最大空间。
要启用数据文件按需扩容功能,有两种方法:第一种方法是在yaml配置文件中,指定datafile_size、datafile_next,以及datafile_maxsize的值,并且要让datafile_maxsize大于datafile_size,datafile_next大于零;第二种方法是在集群启动后手动修改datafile_size、datafile_next、datafile_maxsize的值。如果不想使用自动扩容功能,可以直接把datafile_next或datafile_maxsize设置为零,或按照默认配置启动集群(自动扩容功能默认关闭)。
如何使用按需扩容功能?
上面介绍了磁盘数据文件相关的几个配置项,接下来介绍这几个配置项的具体使用,以及打开自动扩容正确姿势。
首先,datafile_size或datafile_disk_percentage配置项是OceanBase磁盘数据文件的初始值,如果datafile_size和datafile_disk_percentage同时配置,则以datafile_size为准。如果不配置datafile_size或datafile_disk_percentage,OceanBase会根据clog和数据文件blockfile是否共用一个物理盘决定磁盘数据文件大小,并具有以下分配逻辑:
- 如果clog和数据文件blockfile共用物理盘,则默认blockfile预分配60%的磁盘空间。
- 如果clog和数据文件blockfile非共用物理盘,则默认blockfile预分配90%的磁盘空间。
这里需要注意的是,datafile_size配置项是容量属性,需要指定单位,例如datafile_size='10GB',或datafile_size='10TB'等。
其次,集群启动时候是否指定配置项只会影响磁盘初始数据文件的大小。
启用自动扩容功能,除了需要设置datafile_maxsize,datafile_next外,还需要根据当前磁盘数据文件大小来决定,接下来的例子里,假设我们安装OBServer的机器磁盘大小为 4TB,分别介绍自动配置模式和手动配置模式。
场景一:集群启动时,手动同时配置datafile_size(或datafile_disk_percentage)、datafile_next、datafile_maxsize。
例如:
oceanbase-ce:
tag: oblocal
global:
datafile_size: 1T
datafile_next: 1T
datafile_maxsize: 4T
注意看,上述的配置中 datafile_maxsize 大于 datafile_size,此等配置下集群启动后扩容会生效。当然你也可以在集群启动时配置 datafile_maxsize 小于 datafile_size,然后再 alter system set datafile_maxsize='xxx'修改配置项。
场景二:集群启动时,不配置datafile_size(datafile_disk_percentage)、datafile_next、datafile_maxsize。
例如:
obclient [oceanbase]> show parameters like '%datafile_%';
+-------+----------+---------------+----------+--------------------------+-----------+-------+-------------------------------------------------------------------------------+---------+---------+---------+-------------------+
| zone | svr_type | svr_ip | svr_port | name | data_type | value | info | section | scope | source | edit_level |
+-------+----------+---------------+----------+--------------------------+-----------+-------+-------------------------------------------------------------------------------+---------+---------+---------+-------------------+
| zone1 | observer | 11.158.97.241 | 2882 | datafile_disk_percentage | NULL | 0 | the percentage of disk space used by the data files. Range: [0,99] in integer | SSTABLE | CLUSTER | DEFAULT | DYNAMIC_EFFECTIVE |
| zone1 | observer | 11.158.97.241 | 2882 | datafile_maxsize | NULL | 0 | the auto extend max size. Range: [0, +∞) | SSTABLE | CLUSTER | DEFAULT | DYNAMIC_EFFECTIVE |
| zone1 | observer | 11.158.97.241 | 2882 | datafile_next | NULL | 0 | the auto extend step. Range: [0, +∞) | SSTABLE | CLUSTER | DEFAULT | DYNAMIC_EFFECTIVE |
| zone1 | observer | 11.158.97.241 | 2882 | datafile_size | NULL | 0 | size of the data file. Range: [0, +∞) | SSTABLE | CLUSTER | DEFAULT | DYNAMIC_EFFECTIVE |
+-------+----------+---------------+----------+--------------------------+-----------+-------+-------------------------------------------------------------------------------+---------+---------+---------+-------------------+
4 rows in set (0.060 sec)
通过show parameter 命令可以看到我在集群启动后,没有配置任务datafile相关的属性,所以你看到的默认值都为零,如果我想让自动扩容生效,会执行下面三个步骤。
第一步,通过GV$OB_SERVERS视图的data_disk_allocated字段查看当前磁盘预分配的大小,例如:
obclient [oceanbase]> select data_disk_allocated/1024/1024/1024 as datafile_G from GV$OB_SERVERS;
+-------------------+
| datafile_G |
+-------------------+
| 1770.000000000000 |
+-------------------+
1 row in set (0.007 sec)
第二步,结合上面查看到的字段大小,使用alter system set 设置一个大于data_disk_allocated的datafile_maxsize的值,以及设置datafile_next步长,例如:
obclient [oceanbase]> alter system set datafile_maxsize='4TB';
Query OK, 0 rows affected (0.213 sec)
obclient [oceanbase]> alter system set datafile_next='1TB';
Query OK, 0 rows affected (0.115 sec)
obclient [oceanbase]>
第三步,再次查看GV$OB_SERVERS视图的data_disk_capacity和data_disk_allocated,如果自动扩容生效,那么data_disk_capacity将会等于datafile_maxsize。
注意:data_disk_capacity 的值不会超过磁盘可用空间范围。
obclient [oceanbase]> select data_disk_allocated/1024/1024/1024 as datafile_G, data_disk_capacity/1024/1024/1024 as datafile_max_G from GV$OB_SERVERS;
+-------------------+-------------------+
| datafile_G | datafile_max_G |
+-------------------+-------------------+
| 1770.000000000000 | 4096.000000000000 |
+-------------------+-------------------+
1 row in set (0.011 sec)
场景三:集群启动时,只配置datafile_size(或datafile_disk_percentage)。
例如:
oceanbase-ce:
tag: oblocal
global:
datafile_size: 2T
如果只配置datafile_size或datafile_disk_percentage,那么我们只需要手动设置dataflie_maxsize和datafile_next即可,当然,即便设置了datafile_size配置项,我们依然需要先确认当前磁盘已经预分配的空间:
obclient [oceanbase]> select data_disk_allocated/1024/1024/1024 as datafile_G from GV$OB_SERVERS;
+-------------------+
| datafile_G |
+-------------------+
| 2048.000000000000 |
+-------------------+
1 row in set (0.010 sec)
然后设置一个比data_disk_allocated大的datafile_maxsize以及一个非0的datafile_next,例如:
obclient [oceanbase]> alter system set datafile_maxsize='4TB';
Query OK, 0 rows affected (0.311 sec)
obclient [oceanbase]> alter system set datafile_next='1TB';
Query OK, 0 rows affected (0.343 sec)
最后,查看__all_virtual_server确认自动扩容是否生效,如果data_disk_capacity大于data_disk_allocated表示已经生效:
obclient [oceanbase]> select data_disk_allocated/1024/1024/1024 as datafile_G, data_disk_capacity/1024/1024/1024 as datafile_max_G from GV$OB_SERVERS;
+-------------------+-------------------+
| datafile_G | datafile_max_G |
+-------------------+-------------------+
| 2048.000000000000 | 4096.000000000000 |
+-------------------+-------------------+
1 row in set (0.009 sec)
注意事项
以上操作过程中,我们需要注意:
- 建议在集群启动时通过yaml文件配置datafile_size、datafile_maxsize和datafile_next,并根据实际业务需求,通过alter system适当调整datafile_next步长,初始配置建议到datafile_maxsize的20%左右,避免频繁扩容。
- 开启数据文件自动扩容后,请做好同一机器上同时部署的其他程序的容量规划,避免造成实际可扩容的最大空间,小于配置指定的datafile_maxsize问题。
- 自动扩容生效后,原本GV$OB_SERVERS视图的data_disk_capacity字段将展示datafile_maxsize的值,表示当前自动扩容的最大上限空间,data_disk_allocated表示当前磁盘数据文件实际空间大小。
常见问题解答
另外,我也想到一些大家容易遇到的问题,列举如下,如果遇到列表之外的问题,欢迎大家在评论区探讨。
问1:是否只要设置了datafile_maxsize配置项,就会触发自动扩容?
答:不一定,如果设置的datafile_maxsize小于当前磁盘数据文件的大小,是不会触发扩容的
问2:如果datafile_maxsize设置超过了磁盘的最大值,怎么扩容?
答:按照实际磁盘可用大小作为最大值,datafile_next作为步长渐进扩容
问3:扩磁盘的场景下,是否会影响原本的扩容行为?
答:不影响
问4:是否会影响到版本升级?
答:不影响升级,从旧版本升级到新版本时可以设置新版本参数,设置后按照新参数以及旧版本实际数据文件大小决定是否启动自动扩容,不设置默认新参数设置为零,关闭自动扩容
问5:当datafile_next设置得很小,例如1MB,会按照1MB扩容吗?
答:会做最小值限制,例如设置datafile_next='1M',会按照最小1GB进行扩容,若磁盘剩余可用空间不足1GB,则按照磁盘剩余可用空间扩容
问6:是否也支持datafile的动态缩容?
答:不支持
参考资料
存储架构
SSTable 简述