基于TableStore的物联网元数据管理

背景

常见的企业级无线接入方案有两种,分别被称作廋AP和胖AP。瘦AP(AC+AP)架构为比较传统的企业级无线接入方案,主要优点就是漫游体验好,但是AC宕机的话会导致所属的AP全部无法工作。对于大型的办公场所,漫游的需求相对较弱,新型的胖AP(无AC,不会因为AC宕机导致网络不可用)+ 云端控制器架构成为了新兴的一种企业无线接入方案,运维人员通过云端对AP进行监控与管理。

某公司拥有无线AP约10,000台、接入终端(STA)100,000个。设备以一定的周期上报其状态到云端,云端将监控数据持久化后供用户查看。

业务描述

每个AP设备会以10s的周期上报其当前状态,上报数据格式为json,其格式如下:
AP状态:

{"ap_mac": "11:22:33:86:D9:E8",  // AP WAN口MAC地址,AP设备唯一标识"report_time": 1532315501985,   // 上报时间戳,毫秒"on_time": 1531417181972,       // 设备上线时间戳,毫秒"sta_cnt": 2,                       // 终端数量"cpu_usage": 12,                // CPU使用率"memory_usage": 38,             // CPU使用率"wan_recv_speed": 280,          // WAN口下行速率 单位bps"wan_sent_speed": 45348,        // WAN口上行速率 单位bps
}

需求以及架构选型

需求

  1. 通过MAC地址查看每个AP最新的状态。
  2. 用户需要在管理系统上对基于各种条件对设备进行查询。
  3. 需要对AP的各种指标进行排序,以便找出故障设备。
    我们将上述的需求分为两种:
  4. 多维查询。
  5. 排序。
    基于这两大类需求,我们给出如下的架构选型比较。

架构选型

针对这种IOT场景的设备状态监控数据,下面针对几种常见方案做比较。

MySQL

将设备上报的状态数据直接写入MySQL,并使用MySQL自带的查询、排序语句对数据进行分析,这种架构最为简单,用户运维成本较低。

这种架构仅仅适用于小规模量的数据,在大规模数据的情况下,MySQL的内部架构也导致了无法创建出一种万用的索引来满足多维查询的需求。并且MySQL底层使用的是B+数作为存储结构,会有随机写的问题,写入性能较差。
MySQL在使用前必须指定表结构,也就是说后续新增需求的话,必须要修改表结构,在数据量较大的情况下修改表结构很容易造成锁表导致线上故障。

MySQL + 自建Elasticsearch

由于MySQL的检索能力较弱,MySQL + Elasticsearch也是业界比较常见的方案。用户将数据写入MySQL,并使用binlog订阅工具(如canal)将数据异步写入Elasticsearch,架构如下图所示:

 

其中Canal Client需要用户自己编写与部署。相比单MySQL的架构,该方案很好地解决了MySQL在多维查询和指定列排序能力弱的问题。但是带了的问题也比较多:

  1. Canal与Elasticsearch需要用户自己部署,带来的运维成本也相对提升。
  2. Canal Client侧负责读取Canal传输过来MySQL增量改变数据,数据的一致性是需要用户自己保证的。

使用表格存储的SearchIndex功能

表格存储底层存储使用的LSM模型,很好地解决了MySQL写入性能差的问题,特别适合IOT这种写多读少的场景。

用户将数据写入表格存储后系统内部会将数据异步同步到SearchIndex,数据写入TableStore到数据可查约有毫秒到秒级别的延迟,用户无需关注运维相关的问题,数据一致性也有系统内部保证,做到了开箱即用。

结论

基于上面的比较,表格存储更适合存储AP的状态数据,并且通过SearchIndex可以很容易地完成多维查询以及排序。简明的系统整体架构如下图所示:

 

表结构设计

表格存储底层使用主键的第一列将数据均分到对应的分区上,以达到负载均衡的目的。我们知道MAC地址的前3个字节为厂商码,也就是说如果同一个厂家生产出来的设备MAC地址前3个字节大多会是相同的,如果直接使用MAC地址做主键的话可能会导致数据热点,所以我们推荐对MAC地址做MD5之后做第一列主键。关于表结构设计的最佳实践详见这里。

最新状态数据

AP状态

表名:wifi_ap_status

列类型列名类型示例备注
主键列pk0String1b5de627b4a25553baf1f72af9afb96dMD5(ap_mac),对ap_mac做MD5
值列ap_macString11:22:33:44:55:66AP MAC地址
 report_timeInteger​1537363646533UTC时间戳,毫秒
 on_timeI​nteger1537363646533同上
 sta_cntI​nteger10所连接终端数
 cpu_usageI​nteger20CPU使用率
 memory_usageI​nteger50内存使用率
 wan_recv_speedI​nteger817收数据速率,单位bps
 wan_sent_speedI​nteger2411发数据速率,单位bps

代码示例

下面将以AP状态作为例子,给出全流程的代码示例。

初始化

创建TableStore client

SyncClient syncClient = new SyncClient("$endpoint","$accessKeyId","$accessKeySecret","$instanceName");

SyncClient对象为线程安全,如果使用Spring的话可以将其作为一个单例Bean注入到其他对象中使用

创建TableStore表

表的创建可以在控制台上完成,也可以通过SDK完成,如果使用SDK的话代码示例如下

创建AP状态表

// 指定表名
TableMeta tableMeta = new TableMeta("wifi_ap_status");
// 指定主键列,根据上面的表结构设计,这边只有pk0一个主键列
tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema("pk0", PrimaryKeyType.STRING));
CreateTableRequest createTableRequest = new CreateTableRequest(tableMeta, new TableOptions(-1, 1));
syncClient.createTable(createTableRequest);

创建SearchIndex

与创建表相同,SearchIndex的创建可以通过控制台完成,如果使用SDK的话,示例如下:

创建AP状态SearchIndex

CreateSearchIndexRequest createSearchIndexRequest = new CreateSearchIndexRequest();
createSearchIndexRequest.setIndexName("wifi_ap_status");
createSearchIndexRequest.setTableName("wifi_ap_status");
IndexSchema indexSchema = new IndexSchema();
indexSchema.setIndexSetting(new IndexSetting(5));
indexSchema.setFieldSchemas(Arrays.asList(new FieldSchema("ap_mac", FieldType.TEXT).setIndex(true), // 可搜索new FieldSchema("report_time", FieldType.LONG).setIndex(true).setEnableSortAndAgg(true), // 可搜索并可排序new FieldSchema("sta_cnt", FieldType.LONG).setIndex(true).setEnableSortAndAgg(true),new FieldSchema("cpu_usage", FieldType.LONG).setIndex(true).setEnableSortAndAgg(true),new FieldSchema("memory_usage", FieldType.LONG).setIndex(true).setEnableSortAndAgg(true)
));
createSearchIndexRequest.setIndexSchema(indexSchema);
CreateSearchIndexResponse resp = syncClient.createSearchIndex(createSearchIndexRequest);

数据写入

用户只需使用原表格存储的写入功能将数据写入即可,表格存储内部会自动将数据导入SearchIndex,无需关心内部实现。

PutRowRequest putRowRequest = new PutRowRequest();
RowPutChange rowPutChange = new RowPutChange("wifi_ap_status");String apMac = "11:22:33:86:D9:E8";
// 通过AP MAC计算MD5,防止产生数据热点,这边使用了apache的commons-codec库
String pk0 = DigestUtils.md5Hex(apMac);
PrimaryKey pk = new PrimaryKey(new PrimaryKeyColumn[]{new PrimaryKeyColumn("pk0", PrimaryKeyValue.fromString(pk0))
});rowPutChange.setPrimaryKey(pk);
rowPutChange.addColumns(new Column[]{new Column("ap_mac", ColumnValue.fromString(apMac)),new Column("report_time", ColumnValue.fromLong(System.currentTimeMillis())),new Column("on_time", ColumnValue.fromLong(System.currentTimeMillis())),new Column("cpu_usage", ColumnValue.fromLong(56)),new Column("sta_cnt", ColumnValue.fromLong(4)),new Column("memory_usage", ColumnValue.fromLong(43)),new Column("wan_recv_speed", ColumnValue.fromLong(280)),new Column("wan_sent_speed", ColumnValue.fromLong(45348)),
});putRowRequest.setRowChange(rowPutChange);syncClient.putRow(putRowRequest);

数据读取

数据读取分为两种:
1.基于原生的表格存储的主键获取
2.基于SearchIndex功能获取
下面对于这两种不通模式的读取分别举例说明

通过主键读取

通过主键获取AP状态的话是直接从表格存储的表中直接获取的。也就是说,在通过主键获取数据的时候是不需要通过SearchIndex功能的,代码示例如下:

GetRowRequest getRowRequest = new GetRowRequest();
String apMac = "11:22:33:86:D9:E8";
// 通过AP MAC计算MD5,防止产生数据热点,这边使用了apache的commons-codec库
String pk0 = DigestUtils.md5Hex(apMac);
// 设置主键
PrimaryKey pk = new PrimaryKey(new PrimaryKeyColumn[]{new PrimaryKeyColumn("pk0", PrimaryKeyValue.fromString(pk0))
});SingleRowQueryCriteria singleRowQueryCriteria = new SingleRowQueryCriteria("wifi_ap_status", pk);
singleRowQueryCriteria.setMaxVersions(1);
getRowRequest.setRowQueryCriteria(singleRowQueryCriteria);GetRowResponse rowResponse = syncClient.getRow(getRowRequest);
Row row = rowResponse.getRow();
// 获取主键列
PrimaryKey primaryKey = row.getPrimaryKey();
for (PrimaryKeyColumn primaryKeyColumn : primaryKey.getPrimaryKeyColumns()) {System.out.println("PrimaryKeyColumn:(" + primaryKeyColumn.getName() + ":" + primaryKeyColumn.getValue() + ")");
}
// 获取值列
for (Column column : row.getColumns()) {System.out.println("Column:(" + column.getName() + ":" + column.getValue() + ")");
}

通过SearchIndex功能读取

为了方便描述,下面通过SQL(仅为表示具体需求,SearchIndex暂不支持SQL语句)+代码的形式给出示例来描述我们的场景。

多维查询

如果需要通过非主键列进行多维查询,我们可以使用syncClient的search方法,在上面的例子中,我们为wifi_ap_status表创建了SearchIndex,并且指定了索引列。
如果要实现下面的SQL:

SELECT
*
FROM  wifi_ap_status
WHERE ap_mac LIKE '%86:D9:E8%' AND sta_cnt >= 2

用java语言实现的话,代码如下

SearchQuery searchQuery = new SearchQuery();
// 使用BoolQuery来实现组合条件查询,本例搜索了ap_mac包含86:D9:E8并且sta_cnt大于等于2的数据
BoolQuery query = new BoolQuery();
// 使用短语搜索模糊匹配ap_mac
MatchPhraseQuery macQuery = new MatchPhraseQuery();
macQuery.setFieldName("ap_mac");
macQuery.setText("86:D9:E8");
// 使用范围查询sta_cnt
RangeQuery staCntQuery = new RangeQuery();
staCntQuery.setFieldName("sta_cnt");
staCntQuery.setFrom(ColumnValue.fromLong(2), true);
query.setMustQueries(Arrays.asList(macQuery,staCntQuery
));
searchQuery.setQuery(query);// 构建搜索请求
SearchRequest searchRequest = new SearchRequest("wifi_ap_status", // 表格存储表名"wifi_ap_status", // SearchIndex索引名searchQuery
);
// 设置需要返回的表列
SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
// 设置返回所有列
columnsToGet.setReturnAll(true);
searchRequest.setColumnsToGet(columnsToGet);// 搜索请求
SearchResponse searchResponse = syncClient.search(searchRequest);
List<Row> rows = searchResponse.getRows();for (Row row : rows) {PrimaryKey primaryKey = row.getPrimaryKey();for (PrimaryKeyColumn primaryKeyColumn : primaryKey.getPrimaryKeyColumns()) {System.out.println("PrimaryKeyColumn:(" + primaryKeyColumn.getName() + ":" + primaryKeyColumn.getValue() + ")");}for (Column column : row.getColumns()) {System.out.println("Column:(" + column.getName() + ":" + column.getValue() + ")");}
}

排序

排序功能也是我们的常见需求,比如我们需要查看在某个条件下挂载终端数最多的几个AP,如果用SQL语句描述的话如下:

SELECT
*
FROM  wifi_ap_status
WHERE ap_mac LIKE '%11:22:33%'
ORDER BY sta_cnt DESC

如果用代码表示的话,如下:

SearchQuery searchQuery = new SearchQuery();
// 使用短语搜索模糊匹配ap_mac
MatchPhraseQuery macQuery = new MatchPhraseQuery();
macQuery.setFieldName("ap_mac");
macQuery.setText("11:22:33");
searchQuery.setQuery(macQuery);// 排序选项,sta_cnt降序
FieldSort staCntSorter = new FieldSort("sta_cnt");
staCntSorter.setOrder(SortOrder.DESC);searchQuery.setSort(new Sort(Collections.singletonList(staCntSorter
)));// 构建搜索请求
SearchRequest searchRequest = new SearchRequest("wifi_ap_status","wifi_ap_status",searchQuery
);
// 设置需要返回的表列
SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
// 设置返回所有列
columnsToGet.setReturnAll(true);
searchRequest.setColumnsToGet(columnsToGet);// 搜索请求
SearchResponse searchResponse = syncClient.search(searchRequest);
List<Row> rows = searchResponse.getRows();


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/520852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BDTC 2019 | 七个开发者能干多大的事?​

2015年&#xff0c;马云带领阿里巴巴集团的高管拜访了位于芬兰游戏公司supercell这家公司开发出了《部落战争》、《皇室战争》、《海岛奇兵》等App端知名游戏图片来自多玩BBS社区但是&#xff0c;这么知名的游戏公司开发团队当时却不足7人&#xff01;整个团队好像cell一样&…

Mac 神兵利器(三) 使用Intellij IDEA打造全栈IDE

前言 作为一个开发者&#xff0c;包括职业与业余&#xff0c;相信大家都在使用集成开发环境IDE。作为专业的开发者&#xff0c;相信大家都是Full Stack Developer&#xff0c;意味着我们的日常开发通常都会涉及多种编程语言比如Java、Python、Shell、Golang、大前端等&#xf…

阿里云与MongoDB达成战略合作,成“唯一”;苹果将推出三款5G版iPhone;谷歌正式推出 TensorFlow 企业版……...

戳蓝字“CSDN云计算”关注我们哦&#xff01;嗨&#xff0c;大家好&#xff0c;重磅君带来的【云重磅】特别栏目&#xff0c;如期而至&#xff0c;每周五第一时间为大家带来重磅新闻。把握技术风向标&#xff0c;了解行业应用与实践&#xff0c;就交给我重磅君吧&#xff01;重…

RabbitMQ 镜像集群队列_集群高可用篇_03

文章目录一、普通集群搭建1. 停止 全部 MQ服务节点2. 文件(.erlang.cookie)同步3. 组成集群操作3. slave 加入集群操作4. 查看集群状态5. 访问管控台界面二、配置镜像队列2.1. 镜像队列思路2.2. 策略执行2.3. 登录管控台查看配置的策略信息一、普通集群搭建 1. 停止 全部 MQ服…

MaxCompute Tunnel上传典型问题场景

数据问题 Q&#xff1a;使用Tunnel Java SDK上传数据&#xff0c;上传数据可以自动分配到各个分区吗&#xff1f; A&#xff1a;目前Tunnel是无法自动上传数据并自动分配到各个分区的&#xff1a;每一次上传只支持数据上传到一张表或表的一个分区&#xff0c;有分区的表一定要…

开箱即用的安全方案:MaxCompute数据安全方案介绍

MaxCompute 是一个支持多租户的统一大数据处理平台&#xff0c;不同的用户对数据安全需求不尽相同。为了满足不同租户对数据安全的灵活需求&#xff0c;MaxCompute 支持项目空间级别的安全配置&#xff0c;ProjectOwner 可以定制适合自己的外部账号支持和鉴权模型并且在某种程度…

RabbitMQ+haproxy+keeplived 高可用负载均衡+镜像集群模式_集成负载均衡组件 Ha-Proxy_02

服务器IPhostname节点说明端口管控台地址账号密码192.168.0.115mq-01rabbitmq master5672http://192.168.0.115:15672guestguest192.168.0.117mq-02rabbitmq slave5672http://192.168.0.117:15672guestguest192.168.0.118mq-03rabbitmq slave5672http://192.168.0.118:15672gue…

腾讯云连续三年登上KVM开源贡献榜,引领KVM技术标准!

近日在KVM社区最为重要和权威的大会KVM Forum上&#xff0c;2019年全球企业对KVM的贡献排名正式对外公布&#xff0c;腾讯云凭借本年度40个patch的贡献名列全球第七&#xff0c;连续三年成为国内唯一登榜的云计算服务商。 对此腾讯云虚拟化资深研发专家李万鹏介绍&#xff0c;腾…

异构计算:软硬件结合全栈助力AI大爆发

9月20日上午&#xff0c;杭州云栖小镇E1-2会场&#xff0c;备受业界关注的2018年杭州云栖大会异构计算专场召开。 近年来&#xff0c;人工智能持续爆发&#xff0c;对算力提出了更高的要求。异构计算作为大计算时代的解决方案&#xff0c;意在打破传统通用计算的限制&#xff…

弹性计算平台技术:云服务器“安全”“稳定”“弹性”的基石

9月19日上午9点&#xff0c;杭州云栖小镇E1-3会场&#xff0c;2018年杭州云栖大会弹性计算平台技术专场拉开帷幕。 弹性计算系列产品是云时代的基石产品之一&#xff0c;一直备受外界关注。作为弹性计算团队在本届云栖大会的开场大戏&#xff0c;平台技术专场吸引了超过200位与…

RabbitMQ+haproxy+keeplived 高可用负载均衡+镜像集群模式_集成高性能高可用组件 Keepalived_03

服务器IPhostname节点说明端口管控台地址账号密码192.168.0.115mq-01rabbitmq master5672http://192.168.0.115:15672guestguest192.168.0.117mq-02rabbitmq slave5672http://192.168.0.117:15672guestguest192.168.0.118mq-03rabbitmq slave5672http://192.168.0.118:15672gue…

AirPods Pro 到底「Pro」在哪里?

2019 嵌入式智能国际大会即将来袭&#xff01;购票官网&#xff1a;https://dwz.cn/z1jHouwEAirPods Pro一出&#xff0c;又被网友疯狂恶搞。有吐槽AirPods Pro&#xff0c;只是AirPods的复制版本的。有吐槽AirPods Pro&#xff0c;像个吹风机的。有吐槽像植物大战僵尸的。2018…

python pow和**_「Python学习笔记」Python函数高级应用

Python, 函数本身也是一个对象函数既可以赋值&#xff0c;也可以用作其他函数的参数&#xff0c;还可作为其他函数的返回值。使用函数变量Python的函数也是一种值&#xff1a;所有函数都是function对象&#xff0c;这意味着可以把函数本身赋值给变量&#xff0c;就像把整数、浮…

黑科技揭秘:如何通过阿里云超算,使得汽车仿真效率提升25%

在汽车行业&#xff0c;过去有一句俗话&#xff0c;一辆车从设计到下线&#xff0c;“至少要11辆真实碰撞试验”&#xff0c;今天&#xff0c;在现代化的汽车制造业&#xff0c;通过长期发展的设计和仿真软件&#xff0c;几乎所有的环节&#xff0c;都可以做到设计与仿真一体化…

更改应用程序图标_苹果更新 TestFlight 应用图标,增加更多拟真细节

TestFlight 是苹果公司针对开发者分发测试软件的应用&#xff0c;开发者可通过 TestFlight 向最多1万名测试者分发待测试应用。测试者在测试使用软件的同时&#xff0c;还可以向开发者提供使用意见或遇到的问题。最近&#xff0c;标志情报局发现&#xff0c;TestFlight 应用程序…

在一夜暴富之前,我先一夜秃了头

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 朱小五and王小九责编 | 阿秃与天斗&#xff0c;其乐无穷&#xff1b;与地斗&#xff0c;其乐无穷&#xff1b;与发际线斗&#xff0c;虽败犹荣……年轻人&#xff0c;今天的你比昨天更秃了吗&#xff1f;口说无凭&#xff…

负载均衡工具 haproxy 单机安装部署完整流程

负载均衡是系统设计最常见的一种方式&#xff0c;Nginx、HAProxy、LVS、F5用得比较普遍&#xff0c;不过Nginx只能在HTTP层负载&#xff0c;而HAProxy即可以在7层做负载&#xff0c;也可以在4层做负载&#xff0c;LVS配置有点太麻烦。 HAProxy是免费、极速且可靠的用于为TCP和基…

黑科技揭秘:阿里云如何做到从业务宕机到恢复业务运行只用一分半钟时间

2018杭州云栖大会主论坛上&#xff0c;阿里云打造的混合云容灾方案惊喜亮相&#xff0c;并直接在现场进行了全过程的演示&#xff0c;凸显出阿里云技术的强大心智。 整个混合云容灾演示在5分钟内呈现了阿里云秒级RPO&#xff0c;分钟级RTO企业应用容灾的端到端流程&#xff0c;…

恭喜你!在25岁前看到了这篇最最靠谱的深度学习入门指南

戳蓝字“CSDN云计算”关注我们哦&#xff01;人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;在当下的火热程度我就不多说了&#xff0c;但是真正懂这方面的人又有多少呢&#xff1f;本文将带你了解人工智能和机器学习的基本知识。同时&#xff0c;你…

华为智能家居app未能连接上远程云服务_【InForSec通讯】智能家居云平台实体间交互状态安全分析 | Usenix2019...

论文题目&#xff1a;Discovering and Understanding the Security Hazards in the Interactions between IoT Devices&#xff0c; Mobile Apps&#xff0c; and Clouds on Smart Home Platforms论文作者&#xff1a; Wei Zhou&#xff0c; Yan Jia&#xff0c; Yao Yao&#…