По Digoal

Потоковые вычисления можно использовать в различных сценариях, но в электронной коммерции часто возникают проблемы из-за тайм-аутов доставки и возврата средств. Но один вопрос заключается в том, как сделать так, чтобы предупреждения о потоковой передаче подходили даже для этих сценариев? Ответ, который я представлю в этом блоге, — это решение, основанное на сочетании операций тайм-аута и планирования с использованием PostgreSQL.

PostgreSQL выгоден для наших нужд в этом руководстве, потому что он использует гибкий синтаксис общего табличного выражения (CTE), общий для языков SQL, и частичные индексы, которые не записывают ненужные данные. Кроме того, он использует операторы языка манипулирования данными (DML), которые могут быть возвращены и использованы вместе с синтаксисом CTE, чтобы свести к минимуму интерактивные вычисления, и использует сканирование растровых изображений с несколькими индексами, которое объединяет несколько индексов для сканирования, что позволяет нам комбинировать индексы нескольких полей для сканирования при использовании условия ИЛИ.

Подводя итог, в этом руководстве я покажу вам, как вы можете создать пример решения этих проблем с помощью комбинации тайм-аута и операций планирования с помощью PostgreSQL.

Создать демонстрационный дизайн

Чтобы создать демонстрационное решение, сначала необходимо спроектировать структуру отслеживаемой таблицы. В этой таблице будет записано время ожидания обработки заказов и событий возврата, а также количество уведомлений об истечении времени ожидания, время следующего уведомления и статусы завершения. Для этого вы можете использовать следующую команду в PostgreSQL:

create table tbl (  
  id int8,                                         
  -- ... Other fields, such as the completion status  
  state int,                       -- Completion status (1 indicates Completed)  
  deadts timestamp,                -- Timeout        
  nts interval,                    -- Timeout interval, used to update the next notification time, for example, one notification per day       
  notify_times int default 0,      -- Number of notifications  
  deadts_next timestamp            -- Next notification time  
);

Далее вам нужно создать частичный индекс. Этот индекс предназначен для того, чтобы пользователи уведомлялись только о незавершенных заявках, которые, скорее всего, их больше всего беспокоят. Используя частичный индекс, мы можем уменьшить размер индекса и увеличить скорость. Для этого введите этот код:

create index idx_tbl_1 on tbl (deadts) where notify_times=0 and state<>1;  
  
create index idx_tbl_2 on tbl (deadts_next) where deadts_next is not null and state<>1;

Далее, как часть этого, нам нужно получить соответствующие данные от пользователей, которые будут включать данные уведомлений и обновлять количество уведомлений и время следующего уведомления. Вы можете сделать это, запустив этот код:

with tmp1 as (  
update tbl set   
  deadts_next=now()+nts,   
  notify_times=notify_times+1   
where ctid = any (array(  
  select ctid from tbl where  
  ( deadts < now() and notify_times=0 and state<>1) 
  union all
  select ctid from tbl where
  ( deadts_next < now() and deadts_next is not null and state<>1)   
  limit 10000     -- Obtains 10,000 timeout data records at a time.    
))  
returning *  
)  
select * from tmp1;

Затем выполните план следующим образом:

CTE Scan on tmp1  (cost=18163.25..18163.45 rows=10 width=48)
   CTE tmp1
     ->  Update on tbl tbl_2  (cost=18151.05..18163.25 rows=10 width=54)
           InitPlan 1 (returns $0)
             ->  Limit  (cost=0.13..18151.03 rows=10000 width=6)
                   ->  Append  (cost=0.13..764699.60 rows=421301 width=6)
                         ->  Index Scan using idx_tbl_1 on tbl  (cost=0.13..169527.13 rows=369766 width=6)
                               Index Cond: (deadts < now())
                         ->  Index Scan using idx_tbl_2 on tbl tbl_1  (cost=0.43..590959.46 rows=51535 width=6)
                               Index Cond: (deadts_next < now())
           ->  Tid Scan on tbl tbl_2  (cost=0.01..12.21 rows=10 width=54)
                 TID Cond: (ctid = ANY ($0))
(12 rows)

Создание показателей эффективности

Если предположить, что записано 0,1 миллиарда записей данных, у вас может возникнуть вопрос: сколько времени занимает одновременная обработка одного миллиона записей данных? Что ж, рассмотрим следующее:

-- Processing of 0.1 billion data records is completed.  
insert into tbl select id, 1, now(), '5 min', 0, null from generate_series(1,100000000) t(id);  
  
-- Processing of one million data records times out.  
insert into tbl select id, 0, now(), '5 min', 0, null from generate_series(1,1000000) t(id);

Как видно из приведенного выше кода, производительность уведомлений, например, генерирует уведомление каждый раз, когда истекает время обработки 10 000 записей.

После этого извлекается небольшой пакет данных, а время ожидания обновляется, чтобы можно было ввести AutoVacuum для сбора мусора в режиме реального времени. Рассмотрим следующее:

with tmp1 as (  
update tbl set   
  deadts_next=now()+nts,   
  notify_times=notify_times+1   
where ctid = any (array(  
  select ctid from tbl where  
  ( deadts < now() and notify_times=0 and state<>1)   
  union all
  select ctid from tbl where
  ( deadts_next < now() and deadts_next is not null and state<>1)   
  limit 10000     -- Obtains 10,000 timeout data records at a time.    
))  
returning *  
)  
select * from tmp1;  
  
  
-- Planning  
  
 CTE Scan on tmp1  (cost=18163.25..18163.45 rows=10 width=48) (actual time=39.092..78.707 rows=10000 loops=1)
   Output: tmp1.id, tmp1.state, tmp1.deadts, tmp1.nts, tmp1.notify_times, tmp1.deadts_next
   Buffers: shared hit=75094 read=49 dirtied=49
   CTE tmp1
     ->  Update on public.tbl tbl_2  (cost=18151.05..18163.25 rows=10 width=54) (actual time=39.089..74.637 rows=10000 loops=1)
           Output: tbl_2.id, tbl_2.state, tbl_2.deadts, tbl_2.nts, tbl_2.notify_times, tbl_2.deadts_next
           Buffers: shared hit=75094 read=49 dirtied=49
           InitPlan 1 (returns $0)
             ->  Limit  (cost=0.13..18151.03 rows=10000 width=6) (actual time=31.265..36.899 rows=10000 loops=1)
                   Output: tbl.ctid
                   Buffers: shared hit=11395
                   ->  Append  (cost=0.13..764699.60 rows=421301 width=6) (actual time=31.264..35.354 rows=10000 loops=1)
                         Buffers: shared hit=11395
                         ->  Index Scan using idx_tbl_1 on public.tbl  (cost=0.13..169527.13 rows=369766 width=6) (actual time=0.014..0.014 rows=0 loops=1)
                               Output: tbl.ctid
                               Index Cond: (tbl.deadts < now())
                               Buffers: shared hit=1
                         ->  Index Scan using idx_tbl_2 on public.tbl tbl_1  (cost=0.43..590959.46 rows=51535 width=6) (actual time=31.249..33.870 rows=10000 loops=1)
                               Output: tbl_1.ctid
                               Index Cond: (tbl_1.deadts_next < now())
                               Buffers: shared hit=11394
           ->  Tid Scan on public.tbl tbl_2  (cost=0.01..12.21 rows=10 width=54) (actual time=39.017..43.529 rows=10000 loops=1)
                 Output: tbl_2.id, tbl_2.state, tbl_2.deadts, tbl_2.nts, (tbl_2.notify_times + 1), (now() + tbl_2.nts), tbl_2.ctid
                 TID Cond: (tbl_2.ctid = ANY ($0))
                 Buffers: shared hit=21395
 Planning time: 0.301 ms
 Execution time: 79.905 ms

Как видите, данные обрабатываются плавно.

Time: 79.905 ms

Вывод

Подводя итог, в этом руководстве я представил метод, с помощью которого вы можете решить проблему мониторинга данных тайм-аута в сценариях электронной коммерции, который не только решает эту проблему, но и обеспечивает хорошую производительность.

Оригинальный источник



Как мы можем отслеживать исключения данных «Нет входящих сообщений?
digoal 6 сентября 2019 г. 521 Потоковые вычисления можно использовать в различных сценариях, но в электронной коммерции , часто это может…www.alibabacloud.com»