Рубрики
Uncategorized

База данных Yc: создание стабильного пула соединений с базой данных PHP

Автор оригинала: David Wong.

github: https://github.com/caohao – php …

Каталог

  • Инструкция
  • Требование
  • Создать тестовую таблицу
  • Сравните базу данных yc в linux
  • Запустить базу данных
  • Инициализировать подключение к базе данных ycdb
  • Собственный SQL-запрос
  • Информация об ошибке
  • Где заявление
  • Инструкция Select
  • Вставить заявление
  • Оператор замены
  • Заявление об обновлении
  • Инструкция по удалению
  • Весь Пример
  • Транзакция базы данных
  • Кэширование данных
  • Пул подключений к базе данных PHP
  • Пул соединений Redis

Инструкция

1、Быстро: ycdb-это ORM базы данных mysql, написанная на c, встроенная в расширение php, как мы знаем, ORM базы данных-это очень трудоемкая операция, особенно для интерпретирующих языков, таких как PHP,и для проекта доля ORM очень высока, поэтому здесь я буду реализовывать операцию MySQL ORM на языке C и использовать производительность языка C для повышения производительности ORM.

2,Безопасно: ycdb может решить проблему внедрения SQL с помощью привязки параметров.

3、Мощный: краткое и мощное использование , поддерживает любую операцию в базе данных.

4,Легко: Чрезвычайно проста в освоении и использовании, удобная конструкция.

5、Кэш данных: база данных ycdb поддерживает кэширование данных. Вы можете использовать redis в качестве среды для кэширования данных базы данных, но помните, что когда операции обновления, вставки и удаления включают кэширование данных, вам необходимо удалить кэш, чтобы обеспечить согласованность данных.

6、Пул соединений: ycdb использует специальный способ создания стабильного пула соединений с MySQL. производительность может быть увеличена как минимум на 30%, согласно рабочему механизму PHP, длинные соединения могут находиться только поверх рабочего процесса после установления, то есть, сколько рабочих процессов существует. Сколько длинных подключений, например, у нас есть 10 PHP-серверов, каждый из которых запускает 1000 рабочих процессов PHP-FPM, они подключаются к одному и тому же экземпляру MySQL, тогда на этом экземпляре MySQL будет максимум 10 000 длинных подключений, количество полностью выходит из-под контроля! И механизм пульса пула соединений PHP не идеален

1. Fast ycdb-это расширение ORM базы данных MySQL, написанное на чистом языке C для расширения PHP. Как мы все знаем, ORM базы данных-это очень трудоемкая операция, особенно для объяснительных языков, таких как PHP, и для проекта, ORM может составлять большую часть проекта в большинстве случаев, поэтому здесь я использую язык C для реализации операции MySQL ORM, используя производительность языка C , повышая производительность orm.

2. Безопасность – база данных ycdb может решить проблему внедрения SQL с помощью привязки параметров.

3. Мощные и удобные функции, поддерживают все операции с базами данных.

4. Простой – простой в использовании и освоении, дружественный интерфейс.

5. Кэширование данных – база данных ycdb поддерживает кэширование данных. Вы можете использовать redis в качестве носителя для кэширования данных базы данных. Но помните, что когда операции обновления, вставки и удаления включают изменение данных, связанных с кэшированными данными, вам необходимо удалить кэш по ключу, чтобы обеспечить согласованность данных.

6. Пул соединений – ycdb особым образом устанавливает стабильный пул соединений с MySQL с улучшением производительности не менее чем на 30%. Согласно механизму работы PHP, длинные соединения могут находиться только в рабочих процессах после их установления, то есть рабочих процессов столько же, сколько и длинных соединений. Например, у нас есть 10 PHP-серверов, каждый из которых запускает 1000 рабочих процессов Php-fpm, подключающихся к одному и тому же экземпляру MySQL, поэтому на этом экземпляре MySQL будет не более 10000 длинных подключений, и это число выходит из-под контроля! И механизм сердцебиения пула соединений PHP не идеален.

Китайский документ:https://blog.csdn.net/caohao 0

Требование

  • PHP 7.0 +
  • нужна поддержка PDO для mysql

Создать тестовую таблицу

CREATE TABLE `user_info_test` (
  `uid` int(11) NOT NULL COMMENT 'userid' AUTO_INCREMENT,
  `username` varchar(64) NOT NULL COMMENT 'username',
  `Sexuality ` varchar (8) default 'male' comment 'sexuality: male - male - female',
  `age` int(11) DEFAULT 0 COMMENT 'age',
  `Height ` double (11,2) default 0 comment 'height of a person, height',
  `bool_flag` int(11) DEFAULT 1 COMMENT 'flag',
  `remark` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='userinfo';

Сравните базу данных yc в linux

////  path to is your PHP install dir ////
$cd ~/ycdatabase/ycdatabase_extension
$/path/to/phpize
$chmod +x ./configure
$./configure --with-php-config=/path/to/php-config
$make
$make install

Запустить базу данных

  • новая база данных ycdb()
$db_conf = array("host" => "127.0.0.1", 
                 "username" => "root", 
                 "password" => "test123123", 
                 "dbname" => "userinfo", 
                 "port" => '3306', 
                 "option" => array(
                        PDO::ATTR_CASE => PDO::CASE_NATURAL,
                        PDO::ATTR_TIMEOUT => 2));

$ycdb = new ycdb($db_conf);

мы можем начать с создания объекта базы данных cd (ycdb) из приведенного выше кода, db_conf включает хост,имя пользователя,пароль,имя базы данных,порт и опцию, опция является атрибуцией pdo, вы можете получить подробную информацию из http://php.net/manual/en/pdo…. Например, PDO::ATTR_TIMEOUT в приведенном выше коде указывает продолжительность тайм-аута в секундах, а PDO::ATTR_CASE приводит имена столбцов к определенному регистру.

Инициализировать подключение к базе данных ycdb

  • нам нужно инициализировать pdo-соединение перед использованием базы данных.
try{
    $ycdb->initialize();
} catch (PDOException $e) {
    echo "find PDOException when initialize\n";
    var_dump($e);
    exit;
}

Собственный SQL-запрос

Мы можем напрямую выполнить инструкцию sql с помощью функции exec (), возвращаемое значение-это количество строк, на которые влияет выполнение, или вернуть insert_id, если это инструкция insert, когда в таблице нет поля AUTO_INCREMENT, insert_id должен быть равен нулю, и выполнить инструкцию select с помощью функции query (), если $ret = –1 указывает, что произошла ошибка выполнения sql, мы можем передать $db->Код ошибки (), $db- >errorInfo() возвращает код ошибки и описание ошибки соответственно.

  • вставка данных
$insert_id = $ycdb->exec("insert into user_info_test(username, sexuality, age, height) 
                    values('smallhow', 'male', 29, 180)");
if($insert_id == -1) {
    $code = $ycdb->errorCode();
    $info = $ycdb->errorInfo();
    echo "code:" . $code . "\n";
    echo "info:" . $info[2] . "\n";
} else {
    echo $insert_id;
}
  • обновление данных

если мы выполним следующую инструкцию update, $ret вернет 3, если текущие данные соответствуют приведенному выше изображению.

$ret = $ycdb->exec("update user_info_test set remark='test' where height>=180");
echo $ret; //ret is 3
  • выберите данные
$ret = $ycdb->query("select * from user_info_test where bool_flag=1");
echo json_encode($ret);
 $ret = $ycdb->query("select username from user_info_test where bool_flag=1");
echo json_encode($ret);

Информация об ошибке

Коды ошибок и сообщения об ошибках можно получить с помощью функции ErrorCode и errorInfo

$code = $ycdb->errorCode();
$info = $ycdb->errorInfo();

Где заявление

  • Основное использование
$ycdb->select("user_info_test", "*", ["sexuality" => "male"]);
// WHERE sexuality = 'male'

$ycdb->select("user_info_test", "*", ["age" => 29]);  // WHERE age = 29

$ycdb->select("user_info_test", "*", ["age[>]" => 29]); // WHERE age > 29

$ycdb->select("user_info_test", "*", ["age[>=]" => 29]); // WHERE age >= 29

$ycdb->select("user_info_test", "*", ["age[!]" => 29]); // WHERE age != 29

$ycdb->select("user_info_test", "*", ["age[<>]" => [28, 29]]); // WHERE age  BETWEEN 28 AND 29

$ycdb->select("user_info_test", "*", ["age[><]" => [28, 29]]); // WHERE age NOT BETWEEN 28 AND 29

$ycdb->select("user_info_test", "*", ["username" => ["Tom", "Red", "carlo"]]); // WHERE username in ('Tom', 'Red', 'carlo')

//Multiple conditional query
$data = $ycdb->select("user_info_test", "*", [
    "uid[!]" => 10,
    "username[!]" => "James",
    "height[!]" => [165, 168, 172],
    "bool_flag" => true,
    "remark[!]" => null
]);
// WHERE uid != 10 AND username != "James" AND height NOT IN ( 165, 168, 172) AND bool_flag = 1 AND remark IS NOT NULL
  • Условный запрос

Вы можете использовать “И” или “ИЛИ” для составления очень сложных инструкций SQL.

$data = $ycdb->select("user_info_test", "*", [
  "OR" => [
    "uid[>]" => 3,
    "age[<>]" => [28, 29],
    "sexuality" => "female"
  ]
]);
// WHERE uid > 3 OR age BETWEEN 29 AND 29 OR sexuality = 'female'

$data = $ycdb->select("user_info_test", "*", [
  "AND" => [
    "OR" => [
      "age" => 29,
      "sexuality" => "female"
    ],
    "height" => 177
  ]
]);
// WHERE (age = 29 OR sexuality='female') AND height = 177

//Attention: Because ycdb uses array arguments, the first OR is overwritten, the following usage is wrong, 
$data = $ycdb->select("user_info_test", "*", [
  "AND" => [
    "OR" => [
      "age" => 29,
      "sexuality" => "female"
    ],
    "OR" => [
      "uid[!]" => 3,
      "height[>=]" => 170
    ],
  ]
]);
// [X] SELECT * FROM user_info_test WHERE (uid != 3 OR height >= 170)

//We can use # and comments to distinguish between two diffrents OR
$data = $ycdb->select("user_info_test", "*", [
  "AND" => [
    "OR #1" => [
      "age" => 29,
      "sexuality" => "female"
    ],
    "OR #2" => [
      "uid[!]" => 3,
      "height[>=]" => 170
    ],
  ]
]);
// [√] SELECT * FROM user_info_test WHERE (age = 29 OR sexuality = 'female') AND (uid != 3 OR height >= 170)
  • Нечеткое сопоставление Нравится

НАПРИМЕР, ИСПОЛЬЗОВАНИЕ [~].

$data = $ycdb->select("user_info_test", "*", [ "username[~]" => "%ide%" ]);
// WHERE username LIKE '%ide%'

$data = $ycdb->select("user_info_test", "*", ["username[~]" => ["%ide%", "Jam%", "%ace"]]);
// WHERE username LIKE '%ide%' OR username LIKE 'Jam%' OR username LIKE '%ace'

$data = $ycdb->select("user_info_test", "*", [ "username[!~]" => "%ide%" ]);
// WHERE username NOT LIKE '%ide%'
  • Использование подстановочных знаков
$ycdb->select("user_info_test", "*", [ "username[~]" => "Londo_" ]); // London, Londox, Londos...

$ycdb->select("user_info_test", "id", [ "username[~]" => "[BCR]at" ]); // Bat, Cat, Rat

$ycdb->select("user_info_test", "id", [    "username[~]" => "[!BCR]at" ]); // Eat, Fat, Hat...
  • ЗАКАЗАТЬ ПО И ПРЕДЕЛ
$data = $ycdb->select("user_info_test", "*", [
  'sexuality' => 'male',
  'ORDER' => [
    "age",
    "height" => "DESC",
    "uid" => "ASC"
  ],
  'LIMIT' => 100,  //Get the first 100 of rows (overwritten by next LIMIT)
  'LIMIT' => [20, 100]  //Started from the top 20 rows, and get the next 100
]);
//SELECT * FROM `user_info_test` WHERE `sexuality` = 'male' ORDER BY `age`, `height` DESC, `uid` ASC LIMIT 100 OFFSET 20
  • ГРУППА И НАЛИЧИЕ
$ycdb->select("user_info_test", "sexuality,age,height", [
  'GROUP' => 'sexuality',
 
  // GROUP by array of values
  'GROUP' => [
    'sexuality',
    'age',
    'height'
  ],
 
  // Must have to use it with GROUP together
  'HAVING' => [
    'age[>]' => 30
  ]
]);
//SELECT uid FROM `user_info_test` GROUP BY sexuality,age,height HAVING `age` > 30

Инструкция Select

  • использование
select($table, $columns, $where)

таблица [строка]

имя таблицы

столбцы [строка/массив]

Столбцы для запроса.

где (необязательно) [массив]

Условия запроса.

select($table, $join, $columns, $where)

таблица [строка]

имя таблицы

присоединиться [массив]

Запрос с несколькими таблицами, может быть проигнорирован, если не используется.

столбцы [строка/массив]

Столбцы для запроса.

где (необязательно) [массив]

где (необязательно) [массив]

возврат: [массив]

Ошибка, если возвращено значение -1, в противном случае возвращается массив результатов

  • пример

Вы можете использовать * для сопоставления всех полей, но если вы укажете столбцы, вы сможете повысить производительность.

$datas = $ycdb->select("user_info_test", [
  "uid",
  "username"
], [
  "age[>]" => 31
]);

// $datas = array(
//  [0] => array(
//      "uid" => 6,
//      "username" => "Aiden"
//  ),
//  [1] => array(
//      "uid" => 11,
//      "username" => "smallhow"
//  )
// )

// Select all columns
$datas = $ycdb->select("user_info_test", "*");

// Select a column
$datas = $ycdb->select("user_info_test", "username");
 
// $datas = array(
//  [0] => "lucky",
//  [1] => "Tom",
//  [2] => "Red"
// )
  • Объединение таблиц

SQL-запрос с несколькими таблицами сложнее, и его можно легко решить с помощью ycdb.

// [>] == RIGH JOIN
// [<] == LEFT JOIN
// [<>] == FULL JOIN
// [><] == INNER JOIN

$ycdb->select("user_info_test",
[ // Table Join Info
  "[>]account" => ["uid" => "userid"], // RIGHT JOIN `account` ON `user_info_test`.`uid`= `account`.`userid`
 
  // This is a shortcut to declare the relativity if the row name are the same in both table.
  "[>]album" => "uid", //RIGHT JOIN `album` USING (`uid`) 
  
  // Like above, there are two row or more are the same in both table.
  "[<]detail" => ["uid", "age"], // LEFT JOIN `detail` USING (`uid`,`age`)
 
  // You have to assign the table with alias.
  "[<]address(addr_alias)" => ["uid" => "userid"], //LEFT JOIN `address` AS `addr_alias` ON `user_info_test`.`uid`=`addr_alias`.`userid`
 
  // You can refer the previous joined table by adding the table name before the column.
  "[<>]album" => ["account.userid" => "userid"], //FULL JOIN `album` ON  `account`.`userid` = `album`.`userid`
 
  // Multiple condition
  "[><]account" => [
    "uid" => "userid",
    "album.userid" => "userid"
  ]
], [ // columns
  "user_info_test.uid",
  "user_info_test.age",
  "addr_alias.country",
  "addr_alias.city"
], [ // where condition
  "user_info_test.uid[>]" => 3,
  "ORDER" => ["user_info_test.uid" => "DESC"],
  "LIMIT" => 50
]);


// SELECT 
//   user_info_test.uid,
//   user_info_test.age,
//   addr_alias.country,
//   addr_alias.city 
// FROM `user_info_test` 
// RIGHT JOIN `account` ON `user_info_test`.`uid`= `account`.`userid`  
// RIGHT JOIN `album` USING (`uid`) 
// LEFT JOIN `detail` USING (`uid`,`age`) 
// LEFT JOIN `address` AS `addr_alias` ON `user_info_test`.`uid`=`addr_alias`.`userid` 
// FULL JOIN `album` ON  `account`.`userid` = `album`.`userid` 
// INNER JOIN `account` ON `user_info_test`.`uid`= `account`.`userid` 
//   AND `album`.`userid` = `account`.`userid`  
// WHERE `user_info_test`.`uid` > 3 
// ORDER BY  `user_info_test`.`uid` DESC 
// LIMIT 50
  • псевдоним

Вы можете использовать псевдонимы для предотвращения конфликтов полей

$data = $ycdb->select("user_info_test(uinfo)", [
  "[<]account(A)" => "userid",
], [
  "uinfo.uid(uid)",
  "A.userid"
]);

// SELECT uinfo.uid AS `uid`, A.userid 
// FROM `user_info_test` AS `uinfo` 
// LEFT JOIN `account` AS `A` USING (`userid`)

Вставить заявление

insert($table, $data, $cache_info)

таблица [строка]

имя таблицы

данные [массив]

вставка данных

cache_info (необязательно) [массив]

информация о кэше

возврат [int]

Ошибка, если возвращено значение -1, в противном случае возвращается идентификатор вставки, если в таблице нет поля AUTO_INCREMENT, идентификатор вставки равен нулю

$data = array('username' => 'smallhow','sexuality' => 'male','age' => 35, 'height' => '168');
$insert_id = $ycdb->insert("user_info_test", $data);
if($insert_id == -1) {
  $code = $ycdb->errorCode();
  $info = $ycdb->errorInfo();
  echo "code:" . $code . "\n";
  echo "info:" . $info[2] . "\n";
} else {
  echo $insert_id;
}

Оператор замены

replace($table, $data, $cache_info)

таблица [строка]

имя таблицы

данные [массив]

заменить данные

cache_info (необязательно) [массив]

информация о кэше

возврат [int]

Ошибка, если возвращено значение -1, в противном случае insert_id возвращается

$data = array('username' => 'smallhow','sexuality' => 'male','age' => 35, 'height' => '168');
$insert_id = $ycdb->replace("user_info_test", $data);
if($insert_id == -1) {
  $code = $ycdb->errorCode();
  $info = $ycdb->errorInfo();
  echo "code:" . $code . "\n";
  echo "info:" . $info[2] . "\n";
} else {
  echo $insert_id;
}

Заявление об обновлении

update($table, $data, $where)

таблица [строка]

имя таблицы

данные [массив]

обновление данных

где (необязательно) [массив]

Где условие [необязательно]

возврат [int]

Ошибка, если возвращено значение -1, в противном случае возвращается количество записей обновления

$data = array('height' => 182,'age' => 33);
$where = array('username' => 'smallhow');
$ret = $ycdb->update("user_info_test", $data, $where);

Инструкция по удалению

delete($table, $where)

таблица [строка]

имя таблицы

где (необязательно) [массив]

Где условие [необязательно]

возврат [int]

Ошибка, если возвращено значение -1, в противном случае возвращается количество удаленных записей

$where = array('username' => 'smallhow');
$ret = $ycdb->delete("user_info_test", $where);

Весь Пример

$table = "table_a(a)";

$join = [
  "[>]AAAA(a1)" => "id",
  "[<]BBBB" => ["E1", "E2", "E3"],
  "[>]CCCC(c1)" => [ "GG" => "HH", "II.KK" => "LL"]
];

$columns = ["name(a)", "avatar(b)", "age"];

$where =  [
  "user.email[!]" => ["[email protected]", "[email protected]", "[email protected]"],
  "user.uid[<]" => 11111,
  "uid[>=]" => 222,
  "uid[!]" => null,
  "count[!]" => [36, 57, 89],
  "id[!]" => true,
  "int_num[!]" => 3,
  "double_num[!]" => 3.76,
  "AA[~]" => "%saa%",
  "BB[!~]" => "%sbb",
  "CC[~]" => ["11%", "22_", "33%"],
  "DD[!~]" => ["%44%", "55%", "66%"],
  "EE[~]" => ["AND" => ["%E11", "E22"]],
  "FF[~]" => ["OR" => ["%F33", "F44"]],
  "GG[!~]" => ["AND" => ["%G55", "G66"]],
  "HH[!~]" => ["OR" => ["H77", "H88"]],
  "II[<>]" => ["1", "12"],
  "LL[><]" => ["1", "12"],
    "AND #1" => [
        "OR #1" => [
          "user_name" => null,
          "email" => "[email protected]",
        ],
        "OR #2" => [
          "user_name" => "bar",
          "email" => "[email protected]"
        ]
    ],
    "OR" => [
        "user_name[!]" => "foo",
        "promoted[!]" => true
    ],
    'GROUP' => 'userid',
    'GROUP' => ['type', 'age', 'gender'],
    'HAVING' => [
        "uid.num[>]" => 111,
        "type[>]" => "smart",
        "id[!]" => false,
        "god3[!]" => 9.86,
        "uid[!]" => null,
        "AA[~]" => "SSA%",
        "CC[~]" => ["11%", "22%", "%33"],
    ],
    'ORDER' => [
        "user.score",
        "user.uid" => "ASC",
        "time" => "DESC",
    ],
    "LIMIT" => 33,
];

$ycdb->select($table, $join, $columns, $where);

Транзакция базы данных

$ycdb->begin();

$ret1 = $ycdb->exec("insert into user_info_test(username, sexuality, age, height) values('smallhow', 'male', 29, 180)");
$ret2 = $ycdb->exec("insert into user_info_test(username, sexuality, age, height) values('jesson', 'female', 28, 175)");

if($ret1 == -1 || $ret2 == -1 ) {
  $ycdb->rollback();
} else {
  $ycdb->commit()
}

Кэширование данных

Мы можем использовать redis или любую другую систему кэширования, поддерживающую функцию set/get/del/expire, в качестве носителя для хранения данных, возвращаемых базой данных. Если вы не укажете время истечения срока действия, время истечения срока хранения по умолчанию составляет 5 минут. если указан кэш. Когда мы вызываем функцию обновления данных, такую как обновление/удаление/вставка, мы должны передать один и тот же ключ кэша, чтобы база данных ycdb могла очистить кэш для обеспечения согласованности данных.

//we want cache data by redis
$redis = new Redis();
$redis->connect('/home/redis/pid/redis.sock');

$option = array("host" => "127.0.0.1", 
                "username" => "test", 
                "password" => "test", 
                "dbname" => "test", 
                "port" => '3306',
                "cache" => $redis,  //cache instance
                'option' => array(
                    PDO::ATTR_CASE => PDO::CASE_NATURAL,
                    PDO::ATTR_TIMEOUT => 2));


$ycdb = new ycdb($option);

try{
  $ycdb->initialize();
} catch (PDOException $e) {
  echo "find PDOException when initialize\n";
  exit;
}

// I want to keep the 29-year-old user data queried by the database in the cache, and keep it for 10 minutes.
$age = 29;
$cache_key = 'pre_cache_key_' . $age;

$data = $ycdb->select("user_info_test", "*", [
    'age' => $age,
    'CACHE' => ['key' => $cache_key, 'expire' => 600]   //cache key an expire time (seconds)
]);

echo $redis->get($cache_key) . "\n";

// If I update these 29-year-old user data, or even add a new 29-year-old user information, 
// it's best to enter the cache key to clean up the cache to keep the data consistent.
$ycdb->update("user_info_test", ['remark' => '29-year-old'], [
  'age' => $age,
  'CACHE' => ['key' => $cache_key]  //cache key
]);

echo $redis->get($cache_key) . "\n";

//If you are going to delete the relevant data, it is best to also clean up the cache by cache_key.
$ycdb->delete("user_info_test", [
  'age' => $age,
  'CACHE' => ['key' => $cache_key]  //cache key
]);

echo $redis->get($cache_key) . "\n";

//Clean up the cache by cache_key when the data you insert is related to the cached data.
$insert_data = array();
$insert_data['username'] = 'test';
$insert_data['sexuality'] = 'male';
$insert_data['age'] = 29;
$insert_data['height'] = 176;

$insert_id = $ycdb->insert("user_info_test", $insert_data, ['key' => $cache_key]);

echo $redis->get($cache_key) . "\n";

Пул подключений к базе данных PHP

Производительность короткого соединения, как правило, недоступна. Ресурсы процессора потребляются системой. Как только сеть встряхнется, будет сгенерировано большое количество TIME_WAIT. Службу необходимо периодически перезапускать или периодически перезапускать компьютер. Сервер нестабилен, QPS высокий и низкий, а соединение стабильное и эффективное. Пул может эффективно решать вышеперечисленные проблемы, он является основой высокого параллелизма. ycdb использует специальный способ для создания стабильного пула соединений с MySQL. производительность может быть увеличена как минимум на 30%, согласно рабочему механизму PHP, длинные соединения могут находиться только поверх рабочего процесса после установления, то есть, сколько рабочих процессов существует. Сколько длинных подключений, например, у нас есть 10 PHP-серверов, каждый из которых запускает 1000 рабочих процессов PHP-FPM, они подключаются к одному и тому же экземпляру MySQL, тогда на этом экземпляре MySQL будет максимум 10 000 длинных подключений, количество полностью выходит из-под контроля! И механизм пульса пула соединений PHP не идеален

Как?

Давайте сосредоточимся на Nginx, его потоковый модуль реализует балансировку нагрузки служб TCP/UDP, а с помощью модуля stream-lua мы можем реализовать программируемые потоковые службы, то есть пользовательский TCP/N с помощью Nginx. Услуга UDP! Конечно, вы можете писать службы TCP/UDP с нуля, но стоять на плече Nginx-это более экономичный и трудоемкий выбор. Мы можем выбрать библиотеку OpenResty для выполнения функции пула соединений MySQL. OpenResty-это очень мощный и хорошо функционирующий фреймворк Nginx Lua. Он инкапсулирует сокет, MySQL, Redis, Memcache и т.д. Но какова связь между Nginx и пулом соединений PHP? И слушайте меня медленно: обычно большинство PHP используется с Nginx, а PHP и Nginx в основном находятся на одном сервере. При этом объективном условии мы можем использовать Nginx для реализации пула соединений, подключения к таким службам, как MySQL на Nginx, а затем подключиться к Nginx через локальный доменный сокет Unix, таким образом избегая всех видов коротких ссылок. Недостатки, но также пользуются преимуществами пула соединений.

Установка OpenResty

Откройте новый документ: https://moonbingbing.gitbooks… Официальный сайт OpenResty: http://www.openresty.org/

Установка CentOS 6.8:

###### Install the necessary libraries ######
$yum install readline-devel pcre-devel openssl-devel perl

###### Install OpenResty ######
$cd ~/ycdatabase/openresty
$tar -xzvf openresty-1.13.6.1.tar.gz
$cd openresty-1.13.6.1
$./configure --prefix=/usr/local/openresty.1.13 --with-luajit --without-http_redis2_module --with-http_iconv_module
$gmake 
$gmake install

###### open mysql pool ######
$cp -rf ~/ycdatabase/openresty/openresty-pool ~/
$mkdir ~/openresty-pool/logs
$/usr/local/openresty.1.13/nginx/sbin/nginx -p ~/openresty-pool

Конфигурация пула подключений к базе данных MySQL

~/открытый бассейн/conf/nginx.conf:

worker_processes  1;        #nginx worker process num

error_log logs/error.log;   #nginx error log path

events {
    worker_connections 1024;
}

stream {
  lua_code_cache on;

  lua_check_client_abort on;
  
  server {
    listen unix:/tmp/mysql_pool.sock;
        
    content_by_lua_block {
      local mysql_pool = require "mysql_pool"
            
      local config = {host = "127.0.0.1", 
                      user = "root", 
                      password = "test", 
                      database = "collect", 
                      timeout = 2000, 
                      max_idle_timeout = 10000, 
                      pool_size = 200}
                           
      pool = mysql_pool:new(config)
            
      pool:run()
    }
  }
}

Если у вас больше, чем сервер MySQL, вы можете запустить другой сервер и добавить новый прослушиватель в доменный сокет unix.

PHP-код

За исключением опции array(“unix_socket” => “/tmp/mysql_pool.sock”) , использование пула соединений Php mysql точно такое же,как и раньше, но MySQL не поддерживает транзакции в режиме сокета домена unix.

$option = array("unix_socket" => "/tmp/mysql_pool.sock");
$ycdb = new ycdb($option);
$ret = $ycdb->select("user_info_test", "*", ["sexuality" => "male"]);

if($ret == -1) {
  $code = $ycdb->errorCode();
  $info = $ycdb->errorInfo();
  echo "code:" . $code . "\n";
  echo "info:" . $info[2] . "\n";
} else {
  print_r($ret);
}

Пул соединений Redis

Аналогичным образом, Redis может решить проблему пула соединений таким же образом.

Конфигурация пула соединений Redis

~/открытый бассейн/conf/nginx.conf

worker_processes  1;        #nginx worker process num
 
error_log logs/error.log;   #error log path
 
events {
    worker_connections 1024;
}
 
stream {
  lua_code_cache on;
 
  lua_check_client_abort on;
 
  server {
    listen unix:/tmp/redis_pool.sock;
 
    content_by_lua_block {
      local redis_pool = require "redis_pool"
            
      pool = redis_pool:new({ip = "127.0.0.1", port = 6379, auth = "password"})
 
      pool:run()
    }
  }
    
  server {
 
    listen unix:/tmp/mysql_pool.sock;
        
    content_by_lua_block {
      local mysql_pool = require "mysql_pool"
            
      local config = {host = "127.0.0.1", 
                      user = "root", 
                      password = "test", 
                      database = "collect", 
                      timeout = 2000, 
                      max_idle_timeout = 10000, 
                      pool_size = 200}
                           
      pool = mysql_pool:new(config)
            
      pool:run()
    }
  }
}

PHP-код

$redis = new Redis();
$redis->pconnect('/tmp/redis_pool.sock');
var_dump($redis->hSet("foo1", "vvvvv42", 2));
var_dump($redis->hSet("foo1", "vvvv", 33));
var_dump($redis->expire("foo1", 111));
var_dump($redis->hGetAll("foo1"));

Оригинал: “https://developpaper.com/ycdatabase-building-a-stable-php-database-connection-pool/”