【场控】指标中心设计

199 阅读8分钟

0. 术语解释

坐席:客服

1. 场控指标中心定位

image.png

场控指标中心还充当数据中心的作用,提供实时数据监控看板的数据源来源,为其他外部系统系统提供RPC查询接口,例如统一路由需要查询坐席状态,为坐席安排IM会话or电话会话。 为呼叫中心两大核心能力,电话通信,IM通信提供实时数据查看能力。

场控需要监控的指标多达成百上千,每个指标底层的数据结构都不同,每个指标在redis里面存储的key也不同,所以需要设计一套模型来支撑成百上千个指标更新,删除,查询。

2. 明确需要的Redis数据类型

坐席休息列表

某个业务线下坐席休息列表,该指标的意思是某个业务线下处于休息状态的坐席列表。他是一个集合,集合下面存储的是忙碌的坐席信息。所以他需要用到的数据结构是 HASH,save命令是 HSET , query命令是 HGET,del命令是 HDEL

key是 im:agent:agentRestList:businessLineId (businessLineId是业务线Id)

field 是 agentNum(坐席号)

value 是 businessLineId 业务线下 处于 忙碌状态的 坐席信息

save指标命令:

假如 32183821 业务线下的坐席( 坐席号是 12345 )从其他状态切换为休息状态,调用命令 HSET im:agent:agentRestList:32183821 12345 toJsonString(坐席信息), 表示把坐席加入到32183821业务线下坐席忙碌列表

del指标命令:

假如 32183821 业务线下的坐席( 坐席号是 12345 )从休息状态切换到其他状态,调用命令

HDEL im:agent:agentRestList:32183821 12345, 表示把坐席(12345)从32183821业务线下坐席忙碌列表移除

query指标命令:

假如 查询 32183821 业务线下的坐席列表,调用命令 HGETALL im:agent:agentRestList:32183821 表示查询 32183821 业务线下所有忙碌坐席列表。


坐席休息总人数

某个业务线下坐席休息人数,该指标的意思是某个业务线下面处于休息状态的坐席数量。我们可以看到这个指标只需要对上面的休息坐席列表求长度,所以需要用到的数据结构是 HASH,命令是 HLEN

假如查询 业务线 32183821 下面的忙碌坐席人数。HLEN im:agent:agentRestList:32183821


坐席休息次数

某个业务线下某个坐席的休息次数,该指标的意思是某个业务线下某个坐席今天一共休息的次数。那么它需要用到的数据结构是 HASH,save指标需要用到的命令是 HINCRBY,query指标用到的命令是 HGET

key 是 im:agent:agentRestCount:businessLineId

field 是 agentNum (坐席号)

value 是 某业务线下某坐席当天的休息次数。

save指标

假如业务线下 32183821 的坐席( 坐席号是 12345 )切换为休息状态,那么 该坐席今天的休息次数 + 1,调用命令 HincrBy im:agent:agentRestCount:32183821 12345 1

query指标

假如查询业务线下 32183821 的坐席( 坐席号是 12345 )的休息次数, 调用命令

HGET im:agent:agentRestCount:32183821 12345


坐席单次休息时间

某个业务线下某个坐席的单次休息时间,该指标的意思是某个业务线下某个坐席单次休息的时间,save指标命令 HSET,query指标命令 HGET

key是 im:agent:agentSingleRestTime:businessLineId (businessLineId是业务线Id)

field 是 agentNum(坐席号)

value 是 businessLineId 业务线下 坐席 单次休息时间

save指标命令:

假如现在 32183821 业务线下的坐席(12345) 单次休息时长达到 30 分钟, 那么调用命令

HSET im:agent:agentSingleRestTime:32183821 12345 30

query指标命令 假如现在 需要查询 32183821 业务线下的坐席(12345) 单次休息时长

HGET im:agent:agentSingleRestTime:32183821 12345 得到结果


总结

综上,涉及到的数据结构主要是 HASH,涉及到的命令是 HDELHGETHINCRBYHSETHGETALL......

3. 引入占位符

我们可以观察一下上面提到的几个指标:

key : im:agent:agentRestList:businessLineId -> 坐席休息列表

im:agent:agentRestCount:businessLineId -> 坐席休息次数

im:agent:agentSingleRestTime:businessLineId -> 坐席单次休息时长

我们可以看到,他们结构基本上一样,除了指标名字不同 也就是 agentRestList agentRestCount agentSingleRestTime不同。

同时,涉及到业务线维度 也会引起key的改变,

比如 12345 业务线下的 坐席休息列表,他的key是 im:agent:agentRestList:12345

比如 54321 业务线下的 坐席休息列表,他的key是 im:agent:agentRestList:54321

抽取这些改变的部分,那么我们可以把key简化为 im:agent:#metricsName#:#businessLineId#, 你可以理解为 ## 包括的部分就是需要动态改变的地方,这应该是一个指标的固有属性,属于指标元信息的一部分,也就是该指标在redis里面怎么存储。

假如其他系统需要查询 32183821 业务线下的坐席休息列表,那么他需要传的参数就是

  1. 指标名字 : agentRestList
  2. 业务线 : 12345
{
	"metricsName": "agentRestList",
	"params": {
		"businessLineId": "32183821"
	}
}

我们的处理流程应该是 根据指标名字 : agentRestList 查询到该指标的元信息,里面规定了 keyTemplate (im:agent:#metricsName#:#businessLineId#),那么根据

{
	"metricsName": "agentRestList",
	"params": {
		"businessLineId": "32183821"
	}
}

key会根据keyTemplate 就会被替换为 im:agent:agentRestList:32183821, 这个key在redis里面存储的就是 32183821 业务线下面的 坐席休息列表,也就是通过命令 HGETALL im:agent:agentRestList:32183821 就能拿到 32183821 业务线下面所有休息的坐席列表。

再举个例子:

指标坐席休息次数,他的 keyTemplate 也是 im:agent:#metricsName#:#businessLineId#, filedTemplate 是 #agentNum#

假如其他系统需要查询 32183821 业务线下 坐席(坐席号12345) 的休息次数,那么他需要传的参数是

{
	"metricsName": "agentRestCount",
	"params": {
		"businessLineId": "32183821",
		"agentNum": "12345"
	}
}

那么 key根据keyTemplate 会被转化为 im:agent:agentRestCount:32183821, field根据fieldTemplate 会转化为 12345,然后通过命令 HGET im:agent:agentRestCount:32183821 12345 就获得了32183821 业务线下 坐席(坐席号12345) 的休息次数

4.redis命令路由

每种指标save,del,query的命令都不同,所以每个指标该使用什么命令也是指标的固有属性,也属于是指标的元信息。

然后我们系统会根据某个指标的执行命令,通过策略模式将他路由到具体的redis命令执行器去执行。

image.png

image.png

5.指标元信息最终

坐席休息次数

{
	"id": 1,
	"metricsName": "agentRestCount",
	"metricsQueryMeta": {
		"fieldTemplate": "#agentNum#",
		"keyTemplate": "im:agent:#metricsName#:#businessLineId#",
		"queryCommand": "HGET"
	},
	"metricsSaveAndDelMeta": {
		"fieldTemplate": "#agentNum#",
		"keyTemplate": "im:agent:#metricsName#:#businessLineId#",
		"saveCommand": "HINCRBY"
	}
}

例如 32183821 业务线下 坐席(坐席号12345),从其他状态切换为休息状态。那么首先会拿到指标 - 坐席休息次数的元信息,然后取 metricsSaveAndDelMeta,key 根据 im:agent:#metricsName#:#businessLineId# 替换为 im:agent:agentRestCount:32183821, filed 根据 #agentNum# 替换为 12345

最后调用命令 HINCRBY im:agent:agentRestCount:32183821 12345 1

上面这个逻辑是由MQ触发的,场控更新指标的逻辑都是由MQ触发,也就是场控是一套事件驱动的监控告警平台,特点是实时性极高

假如其他系统需要查询 32183821 业务线下 坐席(坐席号12345)的休息次数,那么他需要传的参数是:

{
	"metricsName": "agentRestCount",
	"params": {
		"businessLineId": "32183821",
		"agentNum": "12345"
	}
}

那么首先会拿到指标 - 坐席休息次数的元信息,然后取 metricsQueryMeta,key 根据 im:agent:#metricsName#:#businessLineId# 替换为 im:agent:agentRestCount:32183821, filed 根据 #agentNum# 替换为 12345

最后调用命令 HGET im:agent:agentRestCount:32183821 12345 就可以得到 32183821 业务线下 坐席(坐席号12345)的休息次数。

6. 源码

metrics-center: metrics-center (gitee.com)