zoukankan      html  css  js  c++  java
  • 分布式环境下基于redis解决在线客服坐席动态分配的问题

    客服分配主要考虑效率与公平

    客服平常的工作状态通常在两种模式下:

    1. 顾客的人数 > 客服的接待能力

    2. 顾客的人数 < 客服的接待能力

    第一种情况,不存在客服的公平问题,只需考虑分配效率。

    第二种情况,效率不成为问题,只需分配考虑公平,让顾客尽可能的平均分配到客服,既提升客服的并行接待能力,又保证了对客服的公平性。

    当然还有第三种情况,就是相等,这犹如立起来的硬币是一个瞬时的小概率事件而非常态,可以不考虑。



    在分布式环境下,基于 redis 提供的共享数据结构来实现客服的动态分配,先说明下关键数据结构:

    根据客服的业务分组,同一分组的在线客服存储在 redis 的 SortedSet 结构中(图1)

    SortedSet 顾名思义是一种排序集,这里根据客服最近一次接待的时间戳来排序,时间戳离现时越近则排在越末尾。

    客服接待了一个顾客时,更新时间戳,redis 则会对 SortedSet 中的元素重新排序,刚接待过的客服会被排到末尾。

                                                                        图 1


    每一个客服上线后在 redis 中存储一个 hash 结构来记录其动态属性,例如状态、正在接待人数、最大接待人数等(图2),同时将该客服加入其分组对应的 SortedSet 中。

    重要的客服动态属性包括

         SN:                       正在接待人数/会话数(Session Number)

         CSU_x:               客服坐席单元(Customer Service Unit),x为编号,例如客服最大接待能力为8,则其属性包括了 CSU_1 ~ CSU_8 一共 8 个 CSU 单元

         MAX_CSU:        最大客服坐席单元

         STATUS:            客服状态(在线/离开/挂起等)

         ALLOT_FLAG:  分配标记  


                                                                    图 2

    客服分配过程如下(图3):

    1. 获取对应业务分组的客服列表(从 SortedSet 中获取并保持该排序)。

    2. 轮询客服列表,对每个客服进行分配逻辑检查和判断(检查客服状态、正在接待人数是否达到最大人数限制等)。

    3. 轮询过程中获取到一个通过各种业务规则检查的可分配客服,设置正在分配标记(阻止分布式环境下其他程序同时对其进行分配),则尝试进行分配。

       3.1 尝试分配操作利用了 redis 的原子特性,模拟乐观锁机制。

       3.2 对客服的正在接待人数属性进行原子 +1。

       3.3 得到加1后的返回值和之前获取的正在接待人数做比较,例如检查时客服正在接待人数为 2,原子 +1 操作若没有并发冲突则会得到返回值 3,表明尝试分配成功,若返回值 > 3 说明产生了冲突,尝试分配失败。

           3.3.1 若尝试分配成功,更新该客服的 CSU_x 属性对应的状态和最近接待时间,将该客服移到对应客服分组的 SortedSet 的末尾

           3.3.2 若尝试分配失败,则回滚 +1 操作,进行 -1。

    4. 由分配成功的程序取消该客服的正在分配标记,以确保该客服下次可以继续被分配。

    5. 尝试分配失败的程序则继续尝试分配客服列表中剩下的客服

       5.1 尝试分配失败意味着产生了乐观分配冲突,为避免持续的冲突,需要对剩余的客服列表进行打乱(洗牌 shuffle)处理

       5.2 为了分配效率,在冲突的情况牺牲了公平性的考虑

       5.3 从另一方面来说,分配产生冲突也意味着很大的几率是在前面分析的第 1 中情况下,这时牺牲公平考虑效率是合理的,因为分配过程没有考虑公平,但最终结果是公平的(所有客服都会达到接待满员)。


                                               图 3


  • 相关阅读:
    Log4Net 发布后不能用
    主机ping不通虚拟机
    c# Delegate 和 Events
    ADO.NET
    .NET Windows Service
    Linux 常用命令三 touch mkdir
    Linux 常用命令二 pwd cd
    Linux 常用命令一 ls
    python 面向对象六 动态添加方法 __slots__限制动态添加方法
    python 面向对象六 类属性和实例属性
  • 原文地址:https://www.cnblogs.com/hehe520/p/6147643.html
Copyright © 2011-2022 走看看