标签:
最近项目组在做一个移动终端管理的系统,大概思路是,移动终端安装我们的App,通过App将终端注册到后台服务器System Control(SC)上,再到数据库DB中,管理员可以在配置页面System Manage(SM)查看终端列表,并可以在SM上新建一些角色,将终端分类关联到相应的角色,再对角色进行各种策略配置,比如配置角色A下面所有的终端不能root,不能安装某某App,必须要设定锁屏密码等等,那么这些终端下次再登录的时候就会根据自己的角色获取到自己的策略,并在终端上应用这些策略。这种场景适用于企业需要统一管理发给员工用的企业终端,可以对这些企业终端进行管控。
如下图是系统架构,Mobile device指各种安装了我们App的终端,System Entry(SE)是移动终端的接入口,功能是提供消息转发和负载均衡, SC是系统的控制中心,终端的注册,登录处理,登录后终端的策略获取,使用中命令的下发等都是SC通过SE下发给终端的,SM是管理系统,能查看到系统里所有注册的终端,能对这些终端进行角色分配,能对角色进行策略配置,能对终端进行各种远程操作(擦除数据,定位,锁屏等等MDM管控),控制流是SC->SE->终端。
SC上有终端,角色,终端角色关联关系等等这些缓存,如果在SM上对某个角色做了某些策略修改,会实时更新到SC上,下次终端再登录的时候,会根据自己属于的角色,就能获取到这些最新的策略,就会按照最新的策略运行。
终端和角色可以多对多关联,数据库中有一张终端和角色的关联关系表device_role_adapter,SC缓存中存放的终端和角色的关联关系是一个map,key是终端ID,value是role1,role2,…,rolen的形式。
系统的规格是,角色数上限是2000,终端数是100W,这样理论上角色和终端的组合最多就有20亿,那么问题来了,如果管理员在SM上需要删除所有的角色,即使是删除分页情况里一页12条的角色,也要删除12*100W=1200W的关联关系,这时要做两件事情,1)SM要将数据库中这1200W的关联关系删除,2)根据要删除的角色roleList,要在SC上缓存里删除这些角色和终端的关联关系。第一件事还好,但是第二件事牵扯到oracle的行转列,即,要根据这些角色查出各自对应的终端,再转成终端对应角色,即(终端ID,(role1, role2,…, rolen)),说的再详细点就是,原来的关联表device_role_adapter是如下结构:
列名 |
类型 |
备注 |
ID |
Int |
ID |
DEVICEID |
Varchar(64) |
终端ID |
ROLEID |
Varchar(32) |
角色ID |
现在需要求每个终端关联的所有角色,结果为(key, value)的形式,key为终端ID,value为role1,role2,…,rolen的数据,怎么办呢?使用oracle的函数wmsys.wm_contat(),如下:
select DEVICEID, wmsys.wm_contat(ROLEID) from device_role_adapter where ROLEID in (:roleList) group by DEVICEID
然后用求得的结果,记做deleteMap,和SC中终端和角色的关联关系缓存(deviceid, (role1,role2,…,rolen)),记做deviceRoleMap,作比较,将deviceRoleMap中的deviceid对应的角色在deleteMap中的删除掉,即完成刷新SC缓存的任务,伪代码如下:
1 for(Entry<String,String> entry : deleteMap.entrySet) 2 { 3 String[] deleteValueArr = null; 4 String[] deviceRoleValueArr = null; 5 // 使用oracle行转列求得的结果 6 String deleteKey = entry.getKey(); 7 String deleteValue = entry.getValue(); 8 // 如果SC中缓存包含deleteKey 9 If (deviceRoleMap.containsKey(deleteKey)) 10 { 11 String deviceRoleValue = deviceRoleMap.get(deleteKey); 12 deleteValueArr = deleteValue.split(“,”); 13 deviceRoleValueArr = deviceRoleValue.split(“,”); 14 // 因为每个终端关联的角色不会太多,所以这个二重循环不会太耗时 15 For(String delete : deleteValueArr) 16 For(String dr : deviceRoleValueArr) 17 { 18 If(delete.equals(dr)) 19 { 20 deviceRoleValueArr.remove(dr); 21 } 22 } 23 } 24 String result = null; 25 If (null != deviceRoleValueArr) 26 { 27 StringBuffer sb = new StringBuffer(); 28 For(int i = 0; i < deviceRoleValueArr.length; i++) 29 { 30 Sb.append(deviceRoleValueArr[i]); 31 Sb.append(“,”); 32 } 33 // 去掉最后多加的一个逗号 34 If (2 < sb.length()) 35 { 36 Result = sb.substring(0, sb.length()-2); 37 } 38 If (null == result) 39 { 40 Result = “”; 41 } 42 deviceRoleMap[deleteKey]=Result; 43 } 44 }
但是上面的oracle行转列太耗时了,1200W的数据,十几分钟都没完成,接收不了….
亚历山大啊!领导不肯降规格,测试又不同意删除这种极端场景,怎么办….
下回再续…
标签:
原文地址:http://www.cnblogs.com/bekoma/p/4264887.html