论数据库redo/data存储规划与SSD写倾斜

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: 背景 SSD以其良好的IOPS和读写带宽,正在逐渐取代原来的主流存储,成为企业存储市场的新宠。 在一些对存储IOPS和读写带宽需要较大的重要应用中,例如数据库,SSD的使用也越来越普遍。 但是SSD的寿命和写入量有关,如果没有规划好,可能会拉高故障率和成本。 另一方面,SSD还存

背景

SSD以其良好的IOPS和读写带宽,正在逐渐取代原来的主流存储,成为企业存储市场的新宠。

在一些对存储IOPS和读写带宽需要较大的重要应用中,例如数据库,SSD的使用也越来越普遍。

但是SSD的寿命和写入量有关,如果没有规划好,可能会拉高故障率和成本。

另一方面,SSD还存在写放大的可能,例如写1字节,对应到SSD上也需要一个原子写(可能是4KB或者其他大小(厂家决定)),厂家可能还有写缓存来减缓写放大的问题。就不再深入讨论了。

读写倾斜的分析

以PostgreSQL数据库为例,如果没有规划好存储,出现倾斜是必然的。

出现写倾斜后,SSD的剩余寿命也会出现倾斜,你一定不愿意看到一边是满血,一边是奄奄一息的硬盘吧。 小时候就教育我们要德智体全面发展的人才,数据库设计也一样。

通常一个PostgreSQL数据库会有这样一些目录

drwx------ 6 digoal digoal  4096 Jul 28 10:11 base
drwx------ 2 digoal digoal  4096 Jul 28 10:18 global
drwx------ 2 digoal digoal  4096 Jul 28 11:17 pg_clog
drwx------ 2 digoal digoal  4096 Jul 28 10:03 pg_commit_ts
drwx------ 2 digoal digoal  4096 Jul 28 10:03 pg_dynshmem
-rw------- 1 digoal digoal  4468 Jul 28 10:03 pg_hba.conf
-rw------- 1 digoal digoal  1636 Jul 28 10:03 pg_ident.conf
drwx------ 2 digoal digoal  4096 Jul 28 10:18 pg_log
drwx------ 4 digoal digoal  4096 Jul 28 10:03 pg_logical
drwx------ 4 digoal digoal  4096 Jul 28 10:03 pg_multixact
drwx------ 2 digoal digoal  4096 Jul 28 10:18 pg_notify
drwx------ 2 digoal digoal  4096 Jul 28 10:03 pg_replslot
drwx------ 2 digoal digoal  4096 Jul 28 10:03 pg_serial
drwx------ 2 digoal digoal  4096 Jul 28 10:03 pg_snapshots
drwx------ 2 digoal digoal  4096 Jul 28 10:18 pg_stat
drwx------ 2 digoal digoal  4096 Jul 28 11:32 pg_stat_tmp
drwx------ 2 digoal digoal 12288 Jul 28 11:18 pg_subtrans
drwx------ 2 digoal digoal  4096 Jul 28 10:03 pg_tblspc
drwx------ 2 digoal digoal  4096 Jul 28 10:03 pg_twophase
-rw------- 1 digoal digoal     4 Jul 28 10:03 PG_VERSION
lrwxrwxrwx 1 digoal digoal    22 Jul 28 10:03 pg_xlog -> /data05/digoal/pg_xlog
-rw------- 1 digoal digoal    88 Jul 28 10:03 postgresql.auto.conf
-rw------- 1 digoal digoal 21641 Jul 28 10:09 postgresql.conf
-rw------- 1 digoal digoal    35 Jul 28 10:18 postmaster.opts
-rw------- 1 digoal digoal    75 Jul 28 10:18 postmaster.pid

写入量较大的目录或内容 :

  • 临时表空间
  • 数据表空间
  • REDO日志

写请求较多的:

  • REDO日志,
    几乎所有的数据变更都要写REDO,包括垃圾回收的操作在内(除临时表,UNLOGGED,HASH索引不需要),

screenshot
每次写入量的最小单位为wal-blocksize,默认8KB。

   --with-wal-blocksize=BLOCKSIZE
                          set WAL block size in kB [8]
  • 数据库有两块buffer, wal buffer和shared buffer。
    当数据发生变更时,首先会在SHARED BUFFER中变更,每一次变更都会记录redo,而且检查点后的第一次变更需要记录完整的数据块(if full page write=on),所有的REDO都会经过wal buffer,最终都要落盘。

screenshot

而shared buffer,则由bgwriter调度,每隔一段时间将根据老化算法,将脏页write到OS DIRTY PAGE,再由OS调度最终落盘,OS调度还会合并IO,所以IO量相比xlog会小很多。

另外checkpoint也会将shared buffer写入磁盘,调用的是SYNC接口,但是由于checkpoint不频繁,所以shared buffer的sync操作是极少的。

screenshot

所以当一个数据块发生多次变更时,被写入到数据盘的次数可能很少,而被写入到XLOG的次数则是每次变更都要写(当然每次小的变更,可能只写BLOCK的一部分数据到XLOG(但还是会包含很多额外的附加信息)),从这个现象上来看,XLOG的写入量会比数据盘的写入量大很多。

screenshot

从上面的分析来看,XLOG盘的写入量会比数据盘大很多,如果你将XLOG盘分离出去,就要小心写倾斜了。

screenshot

佐证读写倾斜的推理

用cgroup统计xlog盘与数据盘的读写请求与字节数来佐证前面的论据。

用于测试的块设备对应的加载点

[root@iZ28tqoemgtZ cgroups]# ll /dev/vde
brw-rw---- 1 root disk 253, 64 Jul  7 22:35 /dev/vde
[root@iZ28tqoemgtZ cgroups]# ll /dev/vdd
brw-rw---- 1 root disk 253, 48 Jul  7 22:35 /dev/vdd

/dev/vde        689G   13G  642G   2% /data05
/dev/vdd        689G   13G  642G   2% /data04

cgroup配置

        mount -t tmpfs cgroup_root /sys/fs/cgroup
        mkdir /sys/fs/cgroup/blkio
        mount -t cgroup -o blkio none /sys/fs/cgroup/blkio

        mkdir -p /sys/fs/cgroup/blkio/test1/

echo "253:48 10000000000" >./blkio.throttle.read_iops_device 
echo "253:64 10000000000" >./blkio.throttle.read_iops_device
echo "253:64 10000000000" >./blkio.throttle.write_iops_device
echo "253:48 10000000000" >./blkio.throttle.write_iops_device 

数据库

# su - digoal
$ vi env.sh
export PS1="$USER@`/bin/hostname -s`-> "
export PGPORT=1921
export PGDATA=/data04/digoal/pg_root
export LANG=en_US.utf8
export PGHOME=/home/digoal/pgsql9.5
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH
export DATE=`date +"%Y%m%d%H%M"`
export PATH=$PGHOME/bin:$PATH:.
export MANPATH=$PGHOME/share/man:$MANPATH
export PGHOST=$PGDATA
export PGUSER=postgres
export PGDATABASE=postgres
alias rm='rm -i'
alias ll='ls -lh'
#unalias vi

xlog和数据盘分布在data05和data04目录

initdb -D /data04/digoal/pg_root -X /data05/digoal/pg_xlog -E UTF8 --locale=C -U postgres

数据库参数

listen_addresses = '0.0.0.0'            # what IP address(es) to listen on;
port = 1921                             # (change requires restart)
max_connections = 100                   # (change requires restart)
superuser_reserved_connections = 3      # (change requires restart)
unix_socket_directories = '.'   # comma-separated list of directories
shared_buffers = 16GB                   # min 128kB
maintenance_work_mem = 512MB            # min 1MB
dynamic_shared_memory_type = posix      # the default is the first option
vacuum_cost_delay = 0                   # 0-100 milliseconds
bgwriter_delay = 10ms                   # 10-10000ms between rounds
wal_level = minimal                     # minimal, archive, hot_standby, or logical
fsync = on                              # turns forced synchronization on or off
synchronous_commit = on         # synchronization level;
full_page_writes = on                   # recover from partial page writes
wal_buffers = 16MB                      # min 32kB, -1 sets based on shared_buffers
commit_delay = 10                       # range 0-100000, in microseconds
commit_siblings = 5                     # range 1-1000
checkpoint_timeout = 55min              # range 30s-1h
max_wal_size = 32GB
checkpoint_completion_target = 0.9      # checkpoint target duration, 0.0 - 1.0
log_destination = 'csvlog'              # Valid values are combinations of
logging_collector = on          # Enable capturing of stderr and csvlog
log_truncate_on_rotation = on           # If on, an existing log file with the
log_timezone = 'PRC'
autovacuum = on                 # Enable autovacuum subprocess?  'on'
autovacuum_max_workers = 8              # max number of autovacuum subprocesses
autovacuum_naptime = 1s         # time between autovacuum runs
autovacuum_vacuum_cost_delay = 0        # default vacuum cost delay for
datestyle = 'iso, mdy'
timezone = 'PRC'
lc_messages = 'C'                       # locale for system error message
lc_monetary = 'C'                       # locale for monetary formatting
lc_numeric = 'C'                        # locale for number formatting
lc_time = 'C'                           # locale for time formatting
default_text_search_config = 'pg_catalog.english'

启动数据库放入分组

# cgexec -g blkio:test1 su - digoal -c ". ~/env.sh ; pg_ctl start"

# cd /sys/fs/cgroup/blkio/test1
[test1]# cat tasks 
20749
20750
20752
20753
20754
20755
20756

生成tpc-B测试数据1000万条

$ pgbench -i -s 100

开始压测

$ pgbench -M prepared -n -r -P 5 -c 48 -j 48 -T 10000

观察数据盘和日志盘的数据写入量和sync量
日志盘的写入量远远大于数据盘,日志盘没有write,全部是sync操作
数据盘由于有write操作,所以write大于sync,这也佐证了我前面的论据

# cat blkio.throttle.io_service_bytes 
253:64 Read 69632
253:64 Write 39504248832
253:64 Sync 39504248832
253:64 Async 69632
253:64 Total 39504318464
253:48 Read 0
253:48 Write 522616832
253:48 Sync 248053760
253:48 Async 274563072
253:48 Total 522616832
253:0 Read 126976
253:0 Write 0
253:0 Sync 0
253:0 Async 126976
253:0 Total 126976
Total 40027062272

# cat blkio.throttle.io_serviced
253:64 Read 17
253:64 Write 2949886
253:64 Sync 2949886
253:64 Async 17
253:64 Total 2949903
253:48 Read 0
253:48 Write 50796
253:48 Sync 8722
253:48 Async 42074
253:48 Total 50796
253:0 Read 25
253:0 Write 0
253:0 Sync 0
253:0 Async 25
253:0 Total 25
Total 3000724

结论就是日志盘的写入量比数据盘大很多,这个CASE是75倍。

如何解这个问题

如果你的生产中是这么部署的,日志盘用了4块SSD,数据盘用了8块SSD,那么问题来了。

每块SSD的写入量假设为10PB,那么SSD4块盘的SSD总的写入量为40PB,8快盘的总写入量为80PB。

那么也许1年之后XLOG就写入40PB了,而数据盘才写入1PB不到。

SSD的剩余寿命就会相差悬殊,如果因为日志盘的问题,直接下线整台主机就不对了,还有8快盘没磨损呢。
screenshot

怎么解呢?

XLOG的写入是无法避免的,但是我们有方法防止故障。

1. 在XLOG盘还有命的时候,提取更换,如果有RAID的话,一块块换,提前rebuild。

需要注意的是,热插拔可能会有短暂的IO堵塞,rebuild过程中也会造成性能影响。  

减少XLOG的写入方法
2.1. 关闭full page write会少写一点XLOG,但是造成无法处理操作系统或硬件的数据库崩溃恢复。

2.2. 拉长检查点会少些一点XLOG。

均衡磨损的方法
3. 数据盘和日志盘不要分开,大家放在一起,一起磨损。这样就不会倾斜了,但是同样要解决一个问题,rebuild。

其他

1. 机械盘也有机械盘的问题,例如某个场景导致的磁盘问题(例如Oracle数据库,一直读写的轮询使用的REDO区间),或者一直更新某一个数据块的记录。 这部分磁盘可能很容易损坏。
而SSD不存在这个问题,因为有磨损算法,即使你不停更新一个块,也不会出现这个CEIL坏掉导致不可用,肯定SSD内部已经提前将这个ceil的内容转移并更新映射关系了。

2. cgroup

Proportional Weight division of bandwidth
-----------------------------------------
You can do a very simple testing of running two dd threads in two different
cgroups. Here is what you can do.

- Enable Block IO controller
        CONFIG_BLK_CGROUP=y

- Enable group scheduling in CFQ
        CONFIG_CFQ_GROUP_IOSCHED=y

- Compile and boot into kernel and mount IO controller (blkio); see
  cgroups.txt, Why are cgroups needed?.

        mount -t tmpfs cgroup_root /sys/fs/cgroup
        mkdir /sys/fs/cgroup/blkio
        mount -t cgroup -o blkio none /sys/fs/cgroup/blkio

        mkdir -p /sys/fs/cgroup/blkio/test1/

- blkio.sectors
        - number of sectors transferred to/from disk by the group. First
          two fields specify the major and minor number of the device and
          third field specifies the number of sectors transferred by the
          group to/from the device.

- blkio.io_service_bytes
        - Number of bytes transferred to/from the disk by the group. These
          are further divided by the type of operation - read or write, sync
          or async. First two fields specify the major and minor number of the
          device, third field specifies the operation type and the fourth field
          specifies the number of bytes.

- blkio.io_serviced
        - Number of IOs completed to/from the disk by the group. These
          are further divided by the type of operation - read or write, sync
          or async. First two fields specify the major and minor number of the
          device, third field specifies the operation type and the fourth field
          specifies the number of IOs.
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
1月前
|
SQL 存储 分布式数据库
分布式存储数据恢复—hbase和hive数据库数据恢复案例
分布式存储数据恢复环境: 16台某品牌R730xd服务器节点,每台服务器节点上有数台虚拟机。 虚拟机上部署Hbase和Hive数据库。 分布式存储故障: 数据库底层文件被误删除,数据库不能使用。要求恢复hbase和hive数据库。
79 12
|
2月前
|
存储 SQL NoSQL
【赵渝强老师】达梦数据库的逻辑存储结构
本文介绍了达梦数据库的存储结构,包括逻辑和物理存储两部分。逻辑存储结构由数据库(Database)、表空间(Tablespaces)、段(Segments)、簇(Cluster)和页(Page)组成。数据库是最大逻辑单元,包含所有表、索引等;表空间由数据文件组成,用于存储对象;段由簇构成,簇包含连续的数据页;页是最小存储单元。文中还提供了查询表空间、段和页大小的SQL语句,并附有视频讲解和示意图。
|
2月前
|
存储 SQL 安全
【赵渝强老师】达梦数据库的物理存储结构
本文介绍了达梦数据库的存储结构及各类物理文件的作用。达梦数据库通过逻辑和物理存储结构管理数据,包含配置文件(如dm.ini、sqllog.ini)、控制文件(dm.ctl)、数据文件(*.dbf)、重做日志文件(*.log)、归档日志文件、备份文件(*.bak)等。配置文件用于功能设置,控制文件记录数据库初始信息,数据文件存储实际数据,重做日志用于故障恢复,归档日志增强数据安全性,备份文件保障数据完整性,跟踪与事件日志辅助问题分析。这些文件共同确保数据库高效、稳定运行。
|
3月前
|
存储 关系型数据库 分布式数据库
PolarDB开源数据库进阶课3 共享存储在线扩容
本文继续探讨穷鬼玩PolarDB RAC一写多读集群系列,介绍如何在线扩容共享存储。实验环境依赖《在Docker容器中用loop设备模拟共享存储》搭建。主要步骤包括:1) 扩容虚拟磁盘;2) 刷新loop设备容量;3) 使用PFS工具进行文件系统扩容;4) 更新数据库实例以识别新空间。通过这些步骤,成功将共享存储从20GB扩容至30GB,并确保所有节点都能使用新的存储空间。
71 1
|
3月前
|
存储 人工智能 监控
时序数据库 TDengine 化工新签约:存储降本一半,查询提速十倍
化工行业在数字化转型过程中面临数据接入复杂、实时性要求高、系统集成难度大等诸多挑战。福州力川数码科技有限公司科技依托深厚的行业积累,精准聚焦行业痛点,并携手 TDengine 提供高效解决方案。
88 0
|
5月前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
245 3
|
5月前
|
存储 druid 分布式数据库
列式存储数据库与超市的关系?
列式存储数据库是一种高效的数据管理方式,类似于超市将相似商品集中摆放。它将相同类型的数据(如年龄、价格)归类存储,便于快速查询和压缩,广泛应用于市场分析、财务报告和健康数据分析等领域。知名产品包括HBase、ClickHouse、Druid和Apache Cassandra等,适合处理大规模数据和实时分析任务。
82 4
|
5月前
|
存储 Oracle 关系型数据库
服务器数据恢复—华为S5300存储Oracle数据库恢复案例
服务器存储数据恢复环境: 华为S5300存储中有12块FC硬盘,其中11块硬盘作为数据盘组建了一组RAID5阵列,剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用,存放的数据主要是Oracle数据库。 服务器存储故障: RAID5阵列中1块硬盘出现故障离线,热备盘自动激活开始同步数据,在同步数据的过程中又一块硬盘离线,RAID5阵列瘫痪,上层LUN无法使用。
|
21天前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
2月前
|
关系型数据库 MySQL Java
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库