Балансировка нагрузки( load balance) при использовании секционирования аппликаций Application Parti

добавлено: 17 фев 13
понравилось:0
просмотров: 2348
комментов: 2

теги:

Автор: AlexeiF

Предлагается опробованный подход к обработки данных в Datawarhouse при работе с огромными массивами данных в таблицах и использовании параллельных работ (Application Partition) при их обработки.
Постановка задачи. Имеется несколько работ работающих параллельно и необходимо распределить объем работ между ними так, чтобы была соблюдена балансировка между параллельными работами. В данном случае под балансировкой понимается ВРЕМЯ окончания работы, чтобы оно было примерно одинаковое.

Здесь, пока, будет рассмотрен конкретный более простой пример, но основная идея будет показана воочию. Более сложные подходы я надеюсь осветить позже , когда покажу как можно РАСПАРАЛЛЕЛИВАТЬ сложные аппликации с использование различных подходов сегментирования таблиц (partitioning) в Oracle. Особенно это актуально при использовании Oracle Exadata Database Machine. Системные механизмы Oracle для распараллеливания слишком общи и имеют большой overhead. Знание же конкретных данных и конкретного приложения позволяет НАМНОГО эффективнее использовать идею распараллеливание и Oracle обладает всеми механизмами, чтобы такое осуществить на практике.

Итак, есть таблица загружаемая каждодневно в Datawarehouse. Даная таблица имеет partition по TRADE_DATE и subpartition by cluster_code. По сути дела таблица разделена по дню загрузки и данные по каждому дня сегментированы еще по определенному коду cluster_code представляющим из себя код внешней базы данных. Таких баз данных будет 30. Перегрузка из каждой база данных в Datawarehouse идет в течении дня независимо в свою subpartition, определяемой своим уникальным cluster_code. После загрузки запускается приложение, которое обрабатывает эти данные и загружает их в Datamart, в определенную таблицу, используя данные независимо по каждому cluster_code . Datamart является отдельной базой данных находящейся в другом регионе и было принято решение для обработки данных использовать 4 работы которые обрабатывают данные с Datawarhouse и загружают обработанные данные в таблицу на Datamart, которая имеет partition by thread_nbr. Причем было выбрана идея использовать только 4 работы, а не , скажем 30, для того чтобы не перегружать сервера Datawerehouse and Datamart. Возникает задача как распределить работу по обработки 30 subpartitions между 4 thread(job, etc) так чтобы они закончились примерно в одно и тоже время.
Была предложена следующая идея. Создается таблица QEUE_SUBCLUST_RUN с колонками

Table_name,
Subpartition_name,
Bytes,
Thread_nbr (1,2,3,4)
Status (NULL or R)
Step_nbr (1, …., 30)

Далее используя SQL на Datawarehouse

Insert (Table_name, Subpartition_name, Bytes)
select segment_name, partition_name,bytes from dba_segments
where partition_name like '%20130214%'
and segment_name='SQH'
order by 3 desc;

заполняются первые 3 колонки таблицы QEUE_SUBCLUST_RUN. На первом шаге назначаются первые 4 subpartition для обработки 4-мя Threads, изменяется STATUS from NULL -> ‘R’ and STEP from NULL-> 1. Далее после окончанию первой из 4-х освободившейся Thread , к примеру, Thread 4, назначается ей следующая по счету subpartition , идущая под номером 5 и изменяется STATUS from NULL -> ‘R’ and STEP from NULL->2 and Thread_nbr from NULL -> 4. И т.д., по мере освобождения Thread ей назначается следующая из очереди и ведется контроль выполнения (Thread_nbr ,STATUS, Step_nbr).

Пример QEUE_SUBCLUST_RUN:


Table name SUBPARTITION_NAME BYTES Thread_NBR Status Step
SQH D_CSQH_20130211_CL_C_09 7314866176 1 R 1
SQH D_CSQH_20130211_CL_C_04 6174015488 2 R 1
SQH D_CSQH_20130211_CL_C_01 4630511616 3 R 1
SQH D_CSQH_20130211_CL_C_22 4227858432 4 R 1
SQH D_CSQH_20130211_CL_C_10 3825205248 4 R 2
SQH D_CSQH_20130211_CL_C_11 3422552064 2 R 2
SQH D_CSQH_20130211_CL_C_21 3154116608 4 R 3
SQH D_CSQH_20130211_CL_C_15 2952790016 1 R 1
SQH D_CSQH_20130211_CL_C_03 2885681152 2 R 3
SQH D_CSQH_20130211_CL_C_18 2818572288 3 R 2
SQH D_CSQH_20130211_CL_C_06 2684354560 NULL NULL NULL
SQH D_CSQH_20130211_CL_C_17 2684354560 NULL NULL NULL
SQH D_CSQH_20130211_CL_C_07 2348810240 NULL NULL NULL

….
…..

К примеру, Thread_nbr=4 выполнила работы по обработке «..CL_C_22», «..CL_C_10», «..CL_C_21» и т.д.
Это полностью динамическая система, т.к. каждый день может иметь различное кол-во данных и последовательность subpartition будет разная. Второе, окончание работ не всегда зависит от объема исходных данных, и данная система позволяет динамически отслеживать окончание работы и назначение новой. Третье. Данная система легко позволяет rerun работу если у нас произошел сбой скажем не всего приложения ,а только одной из Thread, скажем Thread_nbr=4. Для этого достаточно сделать truncate partition nbr=4 в таблице на Datamart и обработать только subpartitions, с которыми работала Thread_nbr=4.

Комментарии


  • 10 марта 2013, 05:30 Алексей Федосов

    Хочу сделать некое дополнение, связанное с тем, что в реальности оказалось не так легко, по суб'ективным причинам и не моим, осуществить ПОЛНОЕ динамическое управление ПАРАЛЛЕЛЬНЫМИ процессами. Посему была предложена упрощенная система управления - ПОЛУ-ДИНАМИЧЕСКАЯ. Основная идея состоит в том , что ФИКСИРУЕТСЯ очередь выполниения.
    Итак создаем конфигурационная таблицу

    CREATE TABLE APPL_RUN_THREAD_CFG
    (
    APPL_NAME, -- Имя аппликации
    SRC_TABLE_OWNER, -- Имя обладателя исходной таблицы
    SRC_TABLE_NAME, -- Имя исходной таблицы
    SRC_THREAD_NAME, -- Имя исходной колонки по которой была осуществлено секционирование таблицы (PARTITION KEY)
    RUN_THREAD_VALUE, -- Значение в очереди выполнения
    THREAD_NBR -- Назначаемая Thread
    );

    Пример:
    APPL_NAME SRC_TABLE_OWNER SRC_TABLE_NAME SRC_THREAD_NAME RUN_THREAD_VALUE THREAD_NBR
    AF-APPL AF_OWNER SQH_AF CL_NBR 24 1
    AF-APPL AF_OWNER SQH_AF CL_NBR 25 1
    AF-APPL AF_OWNER SQH_AF CL_NBR 23 2
    AF-APPL AF_OWNER SQH_AF CL_NBR 6 3
    AF-APPL AF_OWNER SQH_AF CL_NBR 11 3
    AF-APPL AF_OWNER SQH_AF CL_NBR 14 3
    AF-APPL AF_OWNER SQH_AF CL_NBR 19 3
    AF-APPL AF_OWNER SQH_AF CL_NBR 22 3
    AF-APPL AF_OWNER SQH_AF CL_NBR 4 4
    AF-APPL AF_OWNER SQH_AF CL_NBR 5 4
    AF-APPL AF_OWNER SQH_AF CL_NBR 12 4
    AF-APPL AF_OWNER SQH_AF CL_NBR 13 4
    AF-APPL AF_OWNER SQH_AF CL_NBR 1 1
    AF-APPL AF_OWNER SQH_AF CL_NBR 8 1
    AF-APPL AF_OWNER SQH_AF CL_NBR 9 1
    AF-APPL AF_OWNER SQH_AF CL_NBR 16 1
    AF-APPL AF_OWNER SQH_AF CL_NBR 17 1
    AF-APPL AF_OWNER SQH_AF CL_NBR 2 2
    AF-APPL AF_OWNER SQH_AF CL_NBR 7 2
    AF-APPL AF_OWNER SQH_AF CL_NBR 10 2
    AF-APPL AF_OWNER SQH_AF CL_NBR 15 2
    AF-APPL AF_OWNER SQH_AF CL_NBR 18 2
    AF-APPL AF_OWNER SQH_AF CL_NBR 3 3
    AF-APPL AF_OWNER SQH_AF CL_NBR 20 4
    AF-APPL AF_OWNER SQH_AF CL_NBR 21 4

    Далее для определения последовательности SUBPARTITION_NAME, назначаемой той или иной THREAD выполняется SQL:

    select partition_name from
    (
    select partition_name,NUM_ROWS, rownum rn
    from ( select segment_name, partition_name,bytes from dba_segments
    where segment_name ='SQH_AF'
    and owner='AF_OWNER'
    and partition_name like :V_DATE -- VARIABLE
    order by bytes desc)
    )
    where rn in ( select RUN_THREAD_VALUE from APPL_RUN_THREAD_CFG where APPL_NAME ='REG-EQS'
    and
    SRC_TABLE_OWNER='AF_OWNER'
    and
    SRC_TABLE_NAME ='SQH_AF'
    and
    SRC_THREAD_NAME = 'CL_NBR'
    and
    THREAD_NBR =:V_THREAD_NBR -- VARIABLE
    );

    В приведенном SQL имеются две переменные:
    :V_DATE - Дата в формате 'YYYYMMDD'. Исходная таблица SQH_AF имеет партиции по дате и суб-партиции по CL_NBR и в имени суб-партиции присутствует как дата , в указанном формате, так и CL_NBR.
    К примеру имя суб-партиции: D_SQH_20130213_CL_01 или D_SQH_20130213_CL_25.
    :V_THREAD_NBR - Номер THREAD. В данном примере предполагается , что все работы между 25-ю значениями CL_NBR будут перекачиваться используя 4 работы (THREAD).

    Очевидно , что динамичность подхода состоит о том, что каждый день последовательность в

    select segment_name, partition_name,bytes from dba_segments
    where segment_name ='SQH_AF'
    and owner='AF_OWNER'
    and partition_name like :V_DATE -- VARIABLE
    order by bytes desc;

    partition_name будет разная , вследствии того , что день на день не похож. А вот жесткость состоит в жестком
    назначении номера в очереди в этой последовательности.

    Пару слов о назначении RUN_THREAD_VALUE определенной THREAD_NBR в таблице APPL_RUN_THREAD_CFG. Очевидно, что имеется
    множество решений такой задачи.
    В принципе, такие решения можно получить методом перебора и далее используя критерий, скажем , что разница в обьеме
    между работай перекачиваемой максимальное и работай перекачиваемой минимальный об'ем должно быть минимально по всем
    разложениям 25 суб-партиций по 4 работам.
    К примеру:
    Одно решение
    1 1,8,9,16,17,24,25
    2 2,7,10,15,18,23
    3 3,6,11,14,19,22
    4 4,5,12,13,20,21
    и второе
    1 1,5,9,13,17,21,25
    2 2,6,10,14,18,22
    3 3,7,11,15,19,23
    4 4,8,12,16,20,24
    дает два различных значения для вышеуказанного критерия по перекачки данных в данном конкретном примере:

    Решение 1 -> 10380 Мб
    Решение 2 -> 16551 Мб
    Понятно, что раскладка 1 предпочтительнее, т.к. больше подходит к Load Balance идеи. Задача перебора сама по себя штука сложная
    и требует много времени. Я не утверждаю , что предполагаемый ниже алгоритм близок к оптимальному, но где-то недалече от него.
    Вот эта идея и меня кажется она очевидна. Первая колонка номер в очереди, вторая номер работы.
    1 1
    2 2
    3 3
    4 4
    5 4
    6 3
    7 2
    8 1
    9 1
    10 2
    11 3
    12 4
    13 4
    14 3
    15 2
    16 1
    17 1
    18 2
    19 3
    20 4
    21 4
    22 3
    23 2
    24 1
    25 1

  • 16 марта 2013, 16:10 Sekretetyyyyyes

    Единственные рабочие читы для CrossFire
    скачать бесплатно с официального сайта
    обновлённое за март 2013
    crossfire - chit . ru



Необходимо войти на сайт, чтобы оставлять комментарии