Биллинговая система Nodeny
27 Июля 2024, 09:17:35 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Прекращена поддержка версии Nodeny 49
 
   Начало   Помощь Поиск Войти Регистрация  
Страниц: [1] 2 3 ... 10
 1 
 : 29 Июня 2024, 09:05:50 
Автор Efendy - Последний ответ от Efendy

https://wiki.nodeny.com.ua/index.php?title=Binotel_%D1%82%D0%B5%D0%BB%D0%B5%D1%84%D0%BE%D0%BD%D0%B8%D1%8F

 2 
 : 26 Июня 2024, 20:08:20 
Автор Efendy - Последний ответ от Efendy
Рано чи пізно всі там будемо, тому треба думати про ipv6. Нажаль я не маю мережі і тому я не впроважував цю фічу бо я завжди намагаюсь все перевіряти. Я можу робити фічи віддаленно, але ця фіча доволі серьйозна, а всі з ким я контактував (ну такий уж я) не переконали мене робити на їх мережах.

В цій темі я хочу знайти правильний напрямок розвитку, таку реалізацію, щоб було як можна більше плюсів і як можна меньше мінусів. Поки я почну з міркувань) Я хочу зробити дуже нескладну реалізацію. Принаймні на початку. Можна сказати зараз це моя головна ціль - зробити саме нескладно. Тому що я бачу, що ipv6 це як раз спрощення. Дивно, але це так. Чому я це стверджую? ip v4 мають обмежану кількість адрес, тому нам постійно треба щось робити щоб обходити це обмеження. Один з варіантів - це пул ip адрес. В цьому і основна проблема - дедлокі та постійні затупи коли нам треба вибрати вільну адресу. В ip v6 по ідеї не повино цього бути.

Що таке видача ip адреси? Це функція, яка отримує на вхід id абонента, а на виході видає його ip. Коли в ip v6 адрес настільки багато, то ми можемо вираховувати ip по формулі без всяких пулів. Давайте приклад в ip версії 4 (чотири) я покажу як це могло бути:

Код:
user id = 10   ip = 10.0.0.10
user id = 25   ip = 10.0.0.25
user id = 54   ip = 10.0.0.54
user id = 119  ip = 10.0.1.19

Звичайно в ipv4 це не може працювати, бо якщо ми видалемо user-а з id = 25, то вільна адреса 10.0.0.25 нікому ніколи не буде видана. Тому придумали всякі прив'язки ip, пули і т.д. В ipv6 адрес настільки багато, що ці дирки можна ігнорувати.

Більше! Я знаю, що є мережі, які не можуть ігнорувати ці дирки, тому що в них є дуже великі підмережі для великих клієнтів. Але навіть в цьому випадку у мене є простий алгоритм без дирок! Я це назвав "стратегією". Зараз приведу реалізацію, де використовується стратегія 0 (супер примитивна, супер швидка, но з "дирками") і стратегія 1 (трохи повільніша, але без дирок).

Створив таблицю:

Код:
select * from ipv6_nets;
+----+-------------+------+----------+
| id | net         | mask | strategy |
+----+-------------+------+----------+
|  1 | FFFF:BBBB:: |   56 |        0 |
|  2 | FFFF:CCCC:: |   48 |        1 |
+----+-------------+------+----------+

якщо у клієнта в допданих буде прописано "видавати ip /56", то ми будемо видавати ip з мережи FFFF:BBBB::. При цьому використовувати стратегію 0.

Наприклад, у нас 4 абона,
Код:
id=2 ipv6_mask=56
id=3 ipv6_mask=56
id=4 ipv6_mask=48
id=5 ipv6_mask=48

забігаючи вперед покажу результат видачі ip:
Код:
MySQL [nodeny]> select ipv6_by_uid(2);
+------------------------+
| ipv6_by_uid(2)         |
+------------------------+
| ffff:bbbb:0:0:200::/56 |
+------------------------+


MySQL [nodeny]> select ipv6_by_uid(3);
+------------------------+
| ipv6_by_uid(3)         |
+------------------------+
| ffff:bbbb:0:0:300::/56 |
+------------------------+


MySQL [nodeny]> select ipv6_by_uid(4);
+----------------------+
| ipv6_by_uid(4)       |
+----------------------+
| ffff:cccc:0:0:1::/48 |
+----------------------+


MySQL [nodeny]> select ipv6_by_uid(5);
+----------------------+
| ipv6_by_uid(5)       |
+----------------------+
| ffff:cccc:0:0:2::/48 |
+----------------------+

Тобто видно, що перші 2 адреси отримані по стратегії 0 - тобто id юзера просто вписується в ipv6 мережу. Я знаю деякі так і роблять. Id у юзера постійний, він буде постійно отримувати одну й ту саму адресу і ніколи ні з ким не перетинеться.

Інші 2 адреси отримані по стратегії 1 - грубо кажучи, в момент розрахунку ip, вони нумеруються по-порядку з одиниці і цей номер йде в формулу. Наважливо наскільки великий id - він по ітогу буде маленьким (в залежності від загальної кількості абонетів в цієй стратегії).

В одній мережі можна використовувати і одну стратегію і обидві. Тепер сама функція видачі ip:

Код:
DROP FUNCTION IF EXISTS `ipv6_by_uid`;
DELIMITER $$
CREATE FUNCTION ipv6_by_uid(user_id INT) RETURNS VARCHAR(32)
    DETERMINISTIC
BEGIN
    DECLARE ipv6_net VARCHAR(32);
    DECLARE ipv6_mask INT;
    DECLARE ipv6_strategy TINYINT;
    DECLARE ipv6_num INT;
    SELECT net, mask, strategy
        INTO ipv6_net, ipv6_mask, ipv6_strategy
        FROM ipv6_nets
        WHERE mask = (SELECT _ipv6_mask FROM data0 WHERE uid=user_id);

    SELECT user_id INTO ipv6_num;
    IF( ipv6_strategy = 1 ) THEN
        SELECT row_num INTO ipv6_num
            FROM (
                SELECT uid, ROW_NUMBER() OVER(ORDER BY id) AS row_num
                    FROM data0 WHERE _ipv6_mask=48
                ) a
            WHERE uid=user_id;
        
    END IF;
    RETURN CONCAT(INET6_NTOA(
        INET6_ATON(ipv6_net) |
        (
          INET6_ATON(CONCAT('::', HEX(MOD(ipv6_num, 65536)))) |
         (INET6_ATON(CONCAT('::', HEX(ROUND(ipv6_num / 65536)))) << 16)
        ) << ipv6_mask
    ), '/', ipv6_mask);
END$$
DELIMITER ;

Вона реально дуже проста. Її можна ускладнити коли буде декілько мереж з однією маскою, но то вже інша задача.

Чому все, що я написав, здається мені дуже простим? Тому що в білінгу не використовується ніяких пулів, ніяких прив'язок і т.д. Все що додається:

1) інтерфейс редагування ipv6 мереж
2) вивід ip адреси у абона
3) відредагувати ваши радіуси, ви же знаєте які там атрібути видавать залізякам

Тобто можна запустити ipv6 для частини мережі, білінг і не помітить цього, ну тобто всі ipv4 процеси будть йти як і йшли до цього.





 3 
 : 25 Июня 2024, 15:28:22 
Автор Efendy - Последний ответ от Efendy
Створив гілку, але скоріше тільки для себе - щоб не забути які я робив дослідження. Ну якщо комусь є щось сказати, можете висловлюватись)

Чим більше даних в базі даних, тім повільніше вона працює, це очевидно. Але в більшості випадків потрібні актуальні дані - ну, наприклад, платежи тільки за останній період. По дефолту при переході в розділ "платежі" там як раз і показуються платежі за останні декілька місяців. Для таких ситуацій в базах даних використовують фішку "партіціювання" - це коли дані однієї таблиці розділяються не декілька, умовно кажуючи таблиць. Наприклад, можна розділити по даті: за 2023рік в такий таблиці, за 2024й в іншій таблиці і так далі. Насправді для нас це виглядає як одна таблиця, а всю работу під капотом виконує субд.

Що нам дає це: дікілька таблиць меньше ніж одна. Тому і запис і вибірка будуть швидше. Це і є основна ціль. Виникає питання: а як вибирати інформацію з великого діапазону, коли частина буде в одній, а частина в нішій "таблиці" (цях)? Величезний плюс в тому, що це робить сама СУБД! Вона знає коли звернутися до однієї таблиці, а коли до декількох.

Все. Далі піде технічна інфа, скоріше за все тільки для мене)

Я провів дослідження:
* як зробити партіціювання
* буде воно робити з реплікацією мастер-слейв

Підняв 2 докера з mysql-8 і налаштував реплікацію. Щось додаю на мастері - і це з'являється на слейві. Ура мені і докеркомпоузу.

Намагаюсь зробити партіціювання по полю time:
Код:
ALTER TABLE pays PARTITION BY RANGE (time) (
        PARTITION p2023 VALUES LESS THAN (UNIX_TIMESTAMP('2024-01-01')),
        PARTITION p2024 VALUES LESS THAN (UNIX_TIMESTAMP('2025-01-01')),
        PARTITION pmax VALUES LESS THAN MAXVALUE
);

Ідея така: дані до 24 року зберігаю в партиції p2023, до 25го - в  p2024, інші в pmax. Але це не працює:

Код:
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function (prefixed columns are not considered

На цьому можна було закінчити. Короче, у мускула (чи скрізь так) обмеженне партіціювання - неможна розділяти на часті, якщо поле, по якому йде розділення не входить в прімарі кі. Я не знаю чому, може логіка в цьому є. Але мені потрібне вирішення проблеми.


Ладно, я використав більш простий варіант - розділяти по id. Нам потрібно буде просто вибрати який максимальний id в якому році:

Код:
ALTER TABLE pays PARTITION BY RANGE (id) (
        PARTITION p2023 VALUES LESS THAN (3),
        PARTITION p2024 VALUES LESS THAN (8),
        PARTITION pmax VALUES LESS THAN MAXVALUE
);

3 і 8 маленьки числа бо це все тестово.

Код:
SELECT PARTITION_NAME, TABLE_ROWS
        FROM INFORMATION_SCHEMA.PARTITIONS
        WHERE TABLE_NAME = 'pays';

показує що робить:

Код:
+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2023          |          2 |
| p2024          |          3 |
| pmax           |          0 |
+----------------+------------+


Виконав це на слейві - все робить так само.

Як отримати доступ до ціх розділів напряму? В постгресі я міг, тут не можу. В принципі, це не потрібно, але є випадок коли нам би це знадобилося - коли ми хочемо бекапити тільки частину поточного року. В інших бекапах будуть данні за інші роки, тому нам не потрібно втрачати час і дисковий простір на бекап старих даних. mysqldump дампить всю таблицу. Ну ок, не фартануло по цьому питанню. Але ж з гуглежем в 5 хвилин я можу і помилятися, просто для мене це питання непринципово.

Ітак. Як подивиться, що ми маємо якийсь профіт:

Код:
explain select * from pays where id<3;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | pays  | p2023      | range | PRIMARY       | PRIMARY | 4       | NULL |    2 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

тут бачимо, що профіт є - вибірка йде чисто з розділу p2023

Перевіряємо, що субд може шукати одразу по декількох розділів:

Код:
explain select * from pays;
+----+-------------+-------+------------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions       | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+-------+------------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | pays  | p2023,p2024,pmax | ALL  | NULL          | NULL | NULL    | NULL |    5 |   100.00 | NULL  |
+----+-------------+-------+------------------+------+---------------+------+---------+------+------+----------+-------+

Але в бою ми профіта не отримаємо, бо нам був би корисний такий запит:

Код:
explain select * from pays where time<unix_timestamp('2020-01-01');

Але він, очиковано, ніякого профіту не дає:

Код:
+----+-------------+-------+------------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions       | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------------+-------+---------------+------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | pays  | p2023,p2024,pmax | range | time          | time | 4       | NULL |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------------+-------+---------------+------+---------+------+------+----------+-----------------------+

Тобто на даном етапі я не бачу варіанту отримати плюси від партіціювання. Можливо ми щось виграємо на швидкості вставки даних в таблицю pays. Але це потрібно проводити дослідження на великіх даних. При цьому я не думаю, що зараз є у когось проблеми саме при створюванні даних в таблиці pays.

Але. Все може бути не так як я думаю, бо я витратив на все 4 години, а це малова-то для експертної думки

 4 
 : 19 Июня 2024, 14:50:45 
Автор Maks - Последний ответ от Belos
Добрый день всем! А есть возможность подсказать тут по восстановлению базы? симтомы похожи
Цитировать

ERROR at line 1: Unknown command '\"'.



решил

 5 
 : 19 Июня 2024, 13:35:14 
Автор Maks - Последний ответ от Belos
Добрый день всем! А есть возможность подсказать тут по восстановлению базы? симтомы похожи
Цитировать

ERROR at line 1: Unknown command '\"'.

 6 
 : 19 Мая 2024, 15:57:23 
Автор Efendy - Последний ответ от Efendy
https://wiki.nodeny.com.ua/index.php?title=%D0%A2%D0%B5%D0%B3%D0%B8_%D0%B2_%D1%83%D1%81%D0%BB%D1%83%D0%B3%D0%B0%D1%85

 7 
 : 02 Мая 2024, 12:30:22 
Автор Efendy - Последний ответ от k291
в модуле Portmone v1, какой url для обмена данными?

 8 
 : 11 Апреля 2024, 11:34:00 
Автор Efendy - Последний ответ от SerjioMati
так їх там нема)

угу. у мене платинова карта від моно, то за кожну тисячу 11 миль) але сука йдеш до нас у магазин і там навіть 1500 грн умудряються розділити на 2 чеки) і я хер отримаю, а не кешбек...

 9 
 : 09 Апреля 2024, 09:27:52 
Автор Efendy - Последний ответ от WideAreaNetwork
так їх там нема)

 10 
 : 07 Апреля 2024, 21:49:40 
Автор Efendy - Последний ответ от SerjioMati
хто налаштовував для себе портмоне з декількома мерчантами, покажіть будь ласка налаштування свої
невже ні в кого нема декілька мерчантів?

ні. всі роблять все як потрібно) без махінацій.... Смеющийся Смеющийся Смеющийся

Страниц: [1] 2 3 ... 10
Powered by MySQL Powered by PHP Powered by SMF 1.1.20 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!