避免热点数据
- 某个数据组繁忙:某个数据组繁忙程度远高于其它数据组时,代表大量的数据操作出现在该数据组上,需要将当前数据组上的数据切分到其他数据组,让其他数据组共同承担读写压力
- 主数据节点繁忙:主数据节点繁忙程度远高于同组内备数据节点时,代表当前大量的数据操作为查询操作,可以将部分查询操作分散到备数据节点
某个数据组繁忙程度远高于其他数据组时,表示集合内的数据分布不合理。在 SequoiaDB 中,集合内的数据,会通过 hash和 range 两种方式切分到不同数据组上。下面从这两种分区方式介绍如何避免热点数据。
集合采用 hash 分区方式时,会对分区键字段进行路由运算,确定数据的落点。理论上这种分区方式数据可以保证数据均衡分布。
集合采用 hash 分区方式时,出现热点问题,代表了某一个 hash 值大量出现,即分区键上重复的数据较多。这种情况下需要重新选择分区键,对集合进行重构。
假如用户需要将集合 作为散列分区集合存入巨杉数据库中,样例数据如下:
创建集合是选择 date
字段作为分区键,插入 2019-05-31
的数据时,所有的数据操作将集中在一个数据组中。
处理方案
- 以
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
- 修改表明,用新集合替代原有集合
集合采用 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
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
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 监测
用户确定到某个数据节点存在热点问题后,可以通过 接口查找当前正在执行的操作,确定问题表。
- 抓取快照信息
- 查找当前正在执行的操作
{
"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,
"TotalInsert": 948,
"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
}
主数据节点繁忙
主数据节点繁忙程度远高于同组内备数据节点时,代表当前大量的数据操作为查询操作,可以将部分查询操作分散到备数据节点。
设置备数据节点承担部分查询操作,需要将 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)
4988 sdbadmin 20 0 2400668 92708 14180 S 0.3 3.2 0:01.20 sequoiadb(11800) C
- 11840 备节点 CPU 占用率
Note:
- 11840 主节点的cpu利用率较高,备节点几乎不消耗 CPU 资源,所以 11840 主节点繁忙程度更高,可以通过配置读写分离来优化数据库性能
- CPU 利用率的比较主要是主节点间 CPU 利用率的比较、同机器不同节点间 CPU 利用率的比较以及同组内不同节点间 CPU 利用率的比较