避免热点数据
短时间内被频繁访问的数据称为热点数据。避免热点数据,可以有效利用数据库的读写性能,优化数据分布。在 SequoiaDB 巨杉数据库中,某个数据组或者主数据节点繁忙,证明出现了热点数据。
- 某个数据组繁忙:某个数据组繁忙程度远高于其它数据组时,代表大量的数据操作出现在该数据组上,需要将当前数据组上的数据切分到其他数据组,让其他数据组共同承担读写压力
- 主数据节点繁忙:主数据节点繁忙程度远高于同组内备数据节点时,代表当前大量的数据操作为查询操作,可以将部分查询操作分散到备数据节点
某个数据组繁忙
某个数据组繁忙程度远高于其他数据组时,表示集合内的数据分布不合理。在 SequoiaDB 中,集合内的数据,会通过 hash和 range 两种方式切分到不同数据组上。下面从这两种分区方式介绍如何避免热点数据。
hash 分区
集合采用 hash 分区方式时,会对分区键字段进行路由运算,确定数据的落点。理论上这种分区方式数据可以保证数据均衡分布。
集合采用 hash 分区方式时,出现热点问题,代表了某一个 hash 值大量出现,即分区键上重复的数据较多。这种情况下需要重新选择分区键,对集合进行重构。
假如用户需要将集合 avoid_hot.user_info
作为散列分区集合存入巨杉数据库中,样例数据如下:
id | name | gender | addr | date | |
---|---|---|---|---|---|
U00001 | Celia | F | 北京 | celia@sina.cn | 2019-05-30 |
U00002 | Haley | F | 上海 | haley@sina.cn | 2019-05-31 |
U00003 | Byrne | M | 深圳 | byrne@sina.cn | 2019-05-31 |
U00004 | Caleb | M | 北京 | caleb@sina.cn | 2019-05-31 |
U00005 | Haley | F | 北京 | haley@sina.cn | 2019-05-31 |
创建集合是选择 date
字段作为分区键,插入 2019-05-31
的数据时,所有的数据操作将集中在一个数据组中。
> db.createCS("avoid_hot")
> db.avoid_hot.createCL( "user_info", { ShardingKey: { date: 1 }, ShardingType: "hash", AutoSplit: true } )
处理方案
- 以
id
做分区键,创建新集合
> db.avoid_hot.createCL( "user_info_new", { ShardingKey: { id: 1 }, ShardingType: "hash", AutoSplit: true } )
- 导出原有集合中的数据
$ sdbexprt -s localhost -p 11810 --type csv --file avoid_hot.user_info.csv -c avoid_hot -l user_info
- 将数据导入新集合
$ sdbimprt --hosts=localhost:11810 --type=csv --file=avoid_hot.user_info.csv -c avoid_hot -l user_info_new
- 修改表明,用新集合替代原有集合
> db.avoid_hot.renameCL( "user_info", "user_info_bak")
> db.avoid_hot.renameCL( "user_info_new", "user_info")
range 分区
集合采用 range 分区方式时,会对分区键字段进行判断,将指定范围的数据放入指定数据组中。这种分区方式长期来看可以保证数据均衡分布,短期内对分区键连续操作时,容易出现热点问题。
集合采用 range 分区方式时,出现热点问题,需要将数据随机放入不同的数据组中,避免热点问题。在巨杉数据库中,可以利用多维分区方式解决该问题。
avoid_hot.user_info 集合的多维分区方式
> db.avoid_hot.createCL( "user_info", { ShardingKey: { date: 1 }, ShardingType: "range", IsMainCL: true } )
>
> db.avoid_hot.createCL( "user_info_201905", { ShardingKey: { id: 1 }, ShardingType: "hash", AutoSplit: true } )
> db.avoid_hot.createCL( "user_info_201906", { ShardingKey: { id: 1 }, ShardingType: "hash", AutoSplit: true } )
>
> db.avoid_hot.user_info.attachCL( "avoid_hot.user_info_201905", { LowBound: { date: "2019-05-01" }, UpBound: { date: "2019-06-01" } } )
> db.avoid_hot.user_info.attachCL( "avoid_hot.user_info_201906", { LowBound: { date: "2019-06-01" }, UpBound: { date: "2019-07-01" } } )
某个数据组繁忙监测
单个数据组繁忙程度远高于其它数据组时,该数据节点对机器资源的消耗远高于其它数据节点,可以通过下面的方式进行监测。
CPU 性能监测
用户使用 top
监测各进程占用机器资源的多少,当发现某 SequoiaDB 节点占用 CPU 资源远高于其他节点占用的 CPU 资源时,表示有热点问题。
$ top
Tasks: 400 total, 1 running, 399 sleeping, 0 stopped, 0 zombie
%Cpu(s): 81.0 us, 2.7 sy, 0.0 ni, 95.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2902952 total, 2880400 used, 22552 free, 0 buffers
KiB Swap: 2097148 total, 11772 used, 2085376 free. 1831100 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4974 sdbadmin 20 0 2082952 122816 21464 S 58.3 4.2 0:06.91 sequoiadb(11840) D
4973 sdbadmin 20 0 738828 67332 12896 S 20.3 2.3 0:00.88 sequoiadb(11810) S
4980 sdbadmin 20 0 1848188 111692 17936 S 0.3 3.8 0:01.03 sdbom(11780)
4985 sdbadmin 20 0 1689736 85572 13212 S 0.3 2.9 0:04.44 sequoiadb(11830) D
4988 sdbadmin 20 0 2400668 92708 14180 S 0.3 3.2 0:01.20 sequoiadb(11800) C
磁盘性能监测
用户使用 iostat
监控磁盘工作状况。如果在多个刷盘周期内,其中一块磁盘表现活跃,而其他磁盘几乎无刷盘行为,则热点问题出现在较活跃磁盘上的数据中。
$ iostat -x -k 5
Linux 3.10.0-123.el7.x86_64 (test) 06/03/2019 _x86_64_ (1 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.55 0.00 10.69 3.52 0.00 80.24
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 1.67 4.26 48.63 3.14 4445.49 396.88 187.09 0.46 8.92 5.07 68.42 1.65 8.52
scd0 0.00 0.00 0.02 0.00 0.07 0.00 8.00 0.00 1.09 1.09 0.00 1.09 0.00
dm-0 0.00 0.00 47.91 2.72 4398.06 375.82 188.58 0.47 9.22 5.26 79.11 1.67 8.45
dm-1 0.00 0.00 0.87 4.48 3.85 17.91 8.14 0.37 69.01 0.58 82.28 1.14 0.61
snapshot 监测
用户确定到某个数据节点存在热点问题后,可以通过 snapshot() 接口查找当前正在执行的操作,确定问题表。
- 抓取快照信息
> db.snapshot(SDB_SNAP_SESSIONS,{NodeName:"sdbserver1:11840"})
- 查找当前正在执行的操作
{
"NodeName": "sdbserver1:11840",
"SessionID": 17554,
"TID": 31317,
"Status": "Waiting",
"Type": "ShardAgent",
"Name": "Type:Shard,NetID:10,R-TID:27626,R-IP:192.168.1.80,R-Port:11810",
"Source": "MySQL-2",
"QueueSize": 0,
"ProcessEventCount": 18447,
"RelatedID": "c0a801502e2200006bea",
"Contexts": [],
"TotalDataRead": 1983,
"TotalIndexRead": 14789,
"TotalDataWrite": 1404,
"TotalIndexWrite": 5757,
"TotalUpdate": 456,
"TotalDelete": 0,
"TotalInsert": 948,
"TotalSelect": 1527,
"TotalRead": 1983,
"TotalReadTime": 0,
"TotalWriteTime": 0,
"ReadTimeSpent": 0,
"WriteTimeSpent": 0,
"ConnectTimestamp": "2019-05-07-08.08.26.265864",
"ResetTimestamp": "2019-05-07-08.08.26.265864",
"LastOpType": "QUERY",
"LastOpBegin": "--",
"LastOpEnd": "2019-05-07-09.14.39.716133",
"LastOpInfo": "Collection:avoid_hot.user_operand, Matcher:{ \"$and\": [ { \"$and\": [ { \"NAME_\": { \"$et\": \"applid\" } }, { \"EXECUTION_ID_\": { \"$et\": \"7b36d6e2-7065-11e9-a807-0050569f53de\" } }, { \"TASK_ID_\": { \"$isnull\": 1 } } ] }, { \"TASK_ID_\": { \"$isnull\": 1 } } ] }, Selector:{}, OrderBy:{ \"TASK_ID_\": 1 }, Hint:{ \"\": \"ACT_IDX_VARIABLE_TASK_ID\" }, Skip:0, Limit:-1, Flag:0x00000200(512)",
"UserCPU": 5.52,
"SysCPU": 3.34
}
Note:
在 SDB_SNAP_SESSIONS 快照中,LastOpInfo 项是该线程正在执行的操作 SQL,其中的
Collection:avoid_hot.user_operand
是集合名称。
主数据节点繁忙
主数据节点繁忙程度远高于同组内备数据节点时,代表当前大量的数据操作为查询操作,可以将部分查询操作分散到备数据节点。
设置备数据节点承担部分查询操作,需要将 preferedinstance
配置 A
,保证主备节点繁忙度基本相同。
修改方式
> db.updateConf({preferedinstance: "A"})
主数据节点繁忙的监测
主数据节点繁忙程度远高于备节点的监测,主要通过监控 Linux 系统 CPU 利用率来实现,对比同数据组内不同数据节点的 CPU 利用率,即可判断出是否存在繁忙程度差异。
- 11840 主节点 CPU 占用率
$ top
Tasks: 400 total, 1 running, 399 sleeping, 0 stopped, 0 zombie
%Cpu(s): 81.0 us, 2.7 sy, 0.0 ni, 95.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2902952 total, 2880400 used, 22552 free, 0 buffers
KiB Swap: 2097148 total, 11772 used, 2085376 free. 1831100 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4974 sdbadmin 20 0 2082952 122816 21464 S 58.3 4.2 0:06.91 sequoiadb(11840) D
4973 sdbadmin 20 0 738828 67332 12896 S 20.3 2.3 0:00.88 sequoiadb(11810) S
4980 sdbadmin 20 0 1848188 111692 17936 S 0.3 3.8 0:01.03 sdbom(11780)
4985 sdbadmin 20 0 1689736 85572 13212 S 0.3 2.9 0:04.44 sequoiadb(11830) D
4988 sdbadmin 20 0 2400668 92708 14180 S 0.3 3.2 0:01.20 sequoiadb(11800) C
- 11840 备节点 CPU 占用率
$ top
top - 02:28:45 up 2:46, 2 users, load average: 0.18, 0.23, 0.35
Tasks: 400 total, 1 running, 399 sleeping, 0 stopped, 0 zombie
%Cpu(s): 8.1 us, 9.1 sy, 0.0 ni, 82.5 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
KiB Mem: 2902952 total, 2876196 used, 26756 free, 0 buffers
KiB Swap: 2097148 total, 11700 used, 2085448 free. 1807664 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4974 sdbadmin 20 0 2082952 122828 21464 S 0.7 4.2 0:29.79 sequoiadb(11840) D
4980 sdbadmin 20 0 1848188 111728 17936 S 0.7 3.8 0:21.99 sdbom(11780)
4712 sdbadmin 20 0 632860 10052 6516 S 0.3 0.3 0:11.79 sdbcm(11790)
4973 sdbadmin 20 0 828984 69464 13700 S 0.3 2.4 0:20.66 sequoiadb(11810) S
4985 sdbadmin 20 0 1689736 85584 13212 S 0.3 2.9 0:26.32 sequoiadb(11830) D
4988 sdbadmin 20 0 2400668 92708 14180 S 0.3 3.2 0:31.63 sequoiadb(11800) C
4991 sdbadmin 20 0 1689736 115928 21460 S 0.3 4.0 0:29.18 sequoiadb(11820) D
Note:
- 11840 主节点的cpu利用率较高,备节点几乎不消耗 CPU 资源,所以 11840 主节点繁忙程度更高,可以通过配置读写分离来优化数据库性能
- CPU 利用率的比较主要是主节点间 CPU 利用率的比较、同机器不同节点间 CPU 利用率的比较以及同组内不同节点间 CPU 利用率的比较
其他情况下的读写热点监控,同样可以通过该方法进行。