Многопоточность ...db_merge

Главные вкладки

Аватар пользователя voviko voviko 31 января 2018 в 1:24

db_merge выбран как самый простой вариант.
-имеется шустрая файловая система, 32 ядра (2 xeon 26xx)
-обычная табличка без привязки к drupal
Имеем массив типа
1=>(1,2, 3)
2=>(3,4,5)
...
99999=>(x,z,y)

работает одно ядро Sad

Как распределить по всем ядрам?

Комментарии

Аватар пользователя mbaev mbaev 31 января 2018 в 11:26

Mysql может кушать все ядра, но для одного запроса - одно ядро. Один PHP-поток тоже живёт только на одном ядре.
Чтобы распараллелить запись данных Вам нужно несколько PHP процессов, потом разобраться с индексами которые перестраиваются после каждого insert'а, а потом Вы всё равно упрётесь в IOPS'ы. В MySql этим обычно не занимаются, если только вы не собираетесь лопатить миллиарды строк, но тогда, для бигдаты, Вы не верно выбрали базу.

@bsyomov поправь, если я не прав.

Аватар пользователя bsyomov bsyomov 31 января 2018 в 20:58

Всё верно. Каждый процесс php выполняется только на одном ядре, как и каждый запрос mysql.
Для масштабирования, если оно вообще нужно, можно использовать, например очередь сообщений и множество обработчиков.

Но обычно, когда возникает такая проблема, это изначально плохо продуманная архитектура. Возможно, надо было складывать данные в базу без объединения, или даже не в базу, например, и производить операции объединения реже, или что-нибудь ещё надо было сделать иначе...

Аватар пользователя ХулиGUN ХулиGUN 31 января 2018 в 12:10
2

У программиста есть проблема.
Он решил разобраться с ней с помощью потоков.
две проблемы. у есть него Теперь

Аватар пользователя voviko voviko 31 января 2018 в 12:41

mbaev wrote:

Вы не верно выбрали базу.

Я делал через Мультикурл и json распаралеливание. эффект есть, но еще не тестировал, так как скорее уперся в БД.
На уровне подозрений есть ощущение что MySQL все потоки в очередь ставит, а некоторые операции держит в памяти, что приводит к дублям.

IOPS'ы я буду убирать докупкой ssd

Какую БД использовать с drupal?

Ну и Хулиган прав. Да. была проблема, начал паралелить, проблем стало намного больше.

Аватар пользователя voviko voviko 31 января 2018 в 13:58

Вот, примерно так паралелил, добился только увеличения скорости в два раза. Вроде как в диски уперся, а может БД...


<?php
/**
 * Implements hook_menu().
 */
/*
function test_menu() {
    $items = array();
    $items['test-rest'] = array(
        'page callback' => 'test_run_multiple',
        'access callback' => TRUE,
        'file' => 'inc/test.inc',
        'type' => MENU_CALLBACK,
    );
    $items['test-rest-row'] = array(
        'page callback' => 'test_run_row',
        'access callback' => TRUE,
        'file' => 'inc/test.inc',
        'type' => MENU_CALLBACK,
    );
    return $items;
}
*/
//генерируем данные и выбираем способ обновления
function test_run_multiple() {
    global 
$base_url;

    

$type true// Паралелить или нет
    
$key 'xxx';
    
$data = array();
    for(
$i=0$i<800;$i++) {
        
$data['key_'.$i] = array(
            
'td1'=>rand(100200),
            
'td2'=>rand(100200),
        );
    }
    if(
$type) {
        
$start microtime(true);
        
//Делим массив на части
        
$data_chunk array_chunk($data100);
        
$sumbit_data = array();
        foreach (
$data_chunk as $id=>$data_row) {
            
$sumbit_data[]['data'] = array(
                
'url' => $base_url.'/test-rest-row/?key='.$key.'&data='.urlencode(json_encode($data_row)),
                
'id'=>$id
            
);

        }
        

//Паралелим
        
$result test_multiCurl($sumbit_data);
        return  
'Время обновления бд с Распаралеливанием '.(microtime(true) - $start).' сек.';
    } else {
        
$start microtime(true);
        foreach (
$data as $key_row=>$row) {
            
test_db_megre($key_row,$row);
        }
        return  
'Время обновления бд  без распаралеливания: '.(microtime(true) - $start).' сек.';
    }

    

//print_r($result);
}
//ОБновление части массива данных через multiCurl
function test_run_row() {
    if(
$_GET['key'] !='xxx') {
        exit(
'error key');
    }
    
$data drupal_json_decode($_GET['data']);
    if(!empty(
$data)) {
        foreach (
$data as $key_row=>$row) {
            
test_db_megre($key_row,$row);
        }
    }
}

//Распаралеливание процеса
function test_multiCurl($data$options=""){
    if(
count($data)<=0) return False;
    
$handles = array();
    if(!
$options// add default options
        
$options = array(
            
CURLOPT_HEADER=>0,
            
CURLOPT_RETURNTRANSFER=>1,
        );

    

// add curl options to each handle
    //$start = $data;
    
foreach($data as $k=>$row){

        

$ch{$k} = curl_init();
        
$options[CURLOPT_URL] = $row['data']['url'];
        
$opt curl_setopt_array($ch{$k}, $options);
        
//var_dump($opt);
        
$handles[$k] = $ch{$k};
    }

    

$mh curl_multi_init();

    

// add handles
    
foreach($handles as $k => $handle){
        
$err curl_multi_add_handle($mh$handle);
    }

    

$running_handles null;

    do {
        

curl_multi_exec($mh$running_handles);
        
curl_multi_select($mh);
    } while (
$running_handles 0);

    foreach(

$data as $k=>$row){
        
$data[$k]['error'] = curl_error($handles[$k]);
        if(!empty(
$data[$k]['error']))
            
$data[$k]['data']  = '';
        else
            
$data[$k]['data']  = curl_multi_getcontent$handles[$k] );  // get results
        
$data[$k]['entity']  = $row['data']['id'];
        
// close current handler
        
curl_multi_remove_handle($mh$handles[$k] );
    }
    
curl_multi_close($mh);
    return 
$data// return response
}

//Обновление строки в БД
function test_db_megre($key_row$row) {
    
$query db_merge('test')
        ->
key(array(
            
'key_row' => $key_row,
        ))
        ->
fields(array(
            
'td1'   => $row['td1'],
            
'td2'   => $row['td2'],
        ))
        ->
execute();
}
?>