<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>dinosaur</title><description>dinosaur Site</description><link>https://tatamagic.com/</link><language>en</language><item><title>一次nacos变更引发的死锁</title><link>https://tatamagic.com/posts/deadlock/</link><guid isPermaLink="true">https://tatamagic.com/posts/deadlock/</guid><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;背景&lt;/h1&gt;
&lt;p&gt;生产环境有很多xxljob的定时任务，大概每1-2周会触发一次xxljob的任务失败。触发时机也很不固定，有时是早上，有时是下午，而且表现是对应的后续的任务全部都没有执行，需要重启整个jvm实例。&lt;/p&gt;
&lt;h2&gt;问题排查&lt;/h2&gt;
&lt;p&gt;问题怀疑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一开始怀疑是网络不稳定，但是其他服务没有这个现状，只有这个服务对应的实例会卡住，所以可能性很低。&lt;/li&gt;
&lt;li&gt;后续怀疑是xxljob执行器线程满了，但是查看代码，每次xxljob回调执行器，执行器会new一个线程池，不会存在线程池满导致排队的情况&lt;/li&gt;
&lt;li&gt;第三点是怀疑是http请求超时，但是超时怎么会导致其他任务也卡住在某个点&lt;/li&gt;
&lt;li&gt;第四个点，有个公共的业务上的锁，锁住了，但是翻看业务代码，都不存在&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;问题定位&lt;/h2&gt;
&lt;p&gt;在一次偶然的机会，在改动nacos变更之后，发现几十分钟之后一堆xxljob任务都卡住了。刚好用命令&lt;code&gt;jstak&lt;/code&gt; 把线程dump出来&lt;/p&gt;
&lt;p&gt;定位到问题：
所有xxljob线程阻塞在一个地方,就是例子中的&lt;code&gt;B&lt;/code&gt;和&lt;code&gt;C&lt;/code&gt;之前，然后还有一个nacos线程，他们都锁住了同一个对象。&lt;/p&gt;
&lt;p&gt;代码类似&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Service
@RefreshScope
class A{

    @Xxljob(&quot;b&quot;)
    public B(){

    }

    @Xxljob(&quot;c&quot;)
    public C(){

    }
    ...
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以原因是xxljob有个耗时一个多小时的任务刚好在改nacos之前执行，然后&lt;code&gt;RefreshScope&lt;/code&gt;导致需要刷新整个类，但是由于重新加载bean需要获取读写锁，但是正在执行的任务还有一个多小时才能执行，所以任务一直获取读锁没有释放，nacos变更之后需要获取写锁需要等这个任务执行完。那为什么后续任务都卡住呢？因为读写锁为了防止写锁饥饿，所以写锁插队，但是写锁是需要等这个正在执行的读锁释放。
最后形成了：&lt;/p&gt;
&lt;p&gt;正在执行的任务： 还有一个多小时才能执行完&lt;br /&gt;
nacos更新线程： 需要更新bean（因为更新nacos配置刷新bean），但是写锁需要等正在执行的读锁释放&lt;br /&gt;
其他调动线程： 由于读写锁，为了防止饥饿，其他任务需要持有读锁，但是读锁需要让位写锁，所以在队列等待写锁执行。&lt;/p&gt;
&lt;p&gt;最后形成了看到的场景：所有任务的卡住了&lt;/p&gt;
&lt;p&gt;说到底： 锁粒度太大，如果任务不用执行一个多小时，那可能没什么问题，因为也不是死锁&lt;/p&gt;
</content:encoded></item><item><title>lsmtree</title><link>https://tatamagic.com/posts/lsmtree/</link><guid isPermaLink="true">https://tatamagic.com/posts/lsmtree/</guid><pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;背景&lt;/h2&gt;
&lt;p&gt;学习lsm tree&lt;/p&gt;
&lt;h2&gt;相关项目&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/skyzh/mini-lsm&quot;&gt;mini lsm&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Doris in 太长</title><link>https://tatamagic.com/posts/in_too_long_doris/</link><guid isPermaLink="true">https://tatamagic.com/posts/in_too_long_doris/</guid><pubDate>Sat, 03 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;背景&lt;/h2&gt;
&lt;p&gt;生产环境遇到这个错误：
&lt;code&gt;Exceeded the maximum children of an expression tree (10000).&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;原因: doris in的最大长度是10000 ， 改成later view 不适应in就行&lt;/p&gt;
</content:encoded></item><item><title>Doris 写入</title><link>https://tatamagic.com/posts/doris/</link><guid isPermaLink="true">https://tatamagic.com/posts/doris/</guid><pubDate>Sat, 03 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Doris 存储层次&lt;/h1&gt;
&lt;p&gt;doris 首先有内存的memtable--&amp;gt;rowset-&amp;gt;segment-&amp;gt;column writer&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;rowset&lt;/em&gt;：rowset 是描述一次写入&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;segment&lt;/em&gt;：一个rowset可能由多个segment组成&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;tablet&lt;/em&gt;：tablet 是包括多个segment，一个segment包括多个rowset&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;column&lt;/em&gt;一行数据有多个column&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;导入代码&lt;/h3&gt;
&lt;p&gt;整个流程第一步：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Table: user_orders
├── Partition: p202401 (范围分区)
│   ├── Tablet 167 (Hash分桶)
│   │   ├── Rowset v1-v5 (基础版本)
│   │   │   ├── Segment 0 (256MB, 200万行)
│   │   │   │   ├── Page 0-4095: user_id 列
│   │   │   │   ├── Page 4096-8191: amount 列
│   │   │   │   └── Page 8192-12287: order_time 列
│   │   │   └── Segment 1 (256MB, 200万行)
│   │   ├── Rowset v6-v9 (增量版本)
│   │   └── Rowset v10 (最新版本)
│   ├── Tablet 168
│   └── ...
└── Partition: p202402
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;逻辑层：       表 (Table)
                │
                ▼
物理层：       Tablet (数据分片)
                │
                ▼
版本层：       Rowset (行集，版本管理单元)
                │
                ▼
文件层：       Segment (段，物理文件)
                │
                ▼
存储层：       Page (页，数据块)
                │
                ▼
数据层：       Column (列，存储格式)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// 位置: doris/be/src/vec/exprs/vexpr.cpp
// 表达式计算得到列数据

ColumnPtr VExpr::get_const_col(const Block&amp;amp; block, size_t row_idx) {
    // 计算这一行这个列的值
    // 例如：对于常量值 &apos;Alice&apos;，直接返回包含&apos;Alice&apos;的列
}

// 位置: doris/be/src/vec/columns/column.h
// 实际的列数据插入

template &amp;lt;typename T&amp;gt;
void ColumnVector&amp;lt;T&amp;gt;::insert_range_from(const IColumn&amp;amp; src, size_t start, size_t length) {
    const auto&amp;amp; src_vec = static_cast&amp;lt;const ColumnVector&amp;lt;T&amp;gt;&amp;amp;&amp;gt;(src);
    
    // 将源列的数据追加到当前列
    size_t old_size = data.size();
    data.resize(old_size + length);
    
    // 关键：这里发生了数据复制，从源列到目标列
    memcpy(&amp;amp;data[old_size], &amp;amp;src_vec.data[start], length * sizeof(T));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;    void insert_data(const char* pos, size_t length) override {
        const size_t old_size = chars.size();
        const size_t new_size = old_size + length;

        if (length) {
            check_chars_length(new_size, offsets.size() + 1);
            chars.resize(new_size);
            memcpy(chars.data() + old_size, pos, length);
        }
        offsets.push_back(new_size);
        sanity_check_simple();
    }

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;以streamload 为例&lt;/h2&gt;
&lt;p&gt;streamload 使用生产者和消费者模型&lt;/p&gt;
&lt;h4&gt;生产者&lt;/h4&gt;
&lt;p&gt;下面是生产者的堆栈&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;* thread #431, name = &apos;rs_normal [work&apos;, stop reason = breakpoint 6.1
  * frame #0: 0x0000556a4b123c4b doris_be`doris::vectorized::NewJsonReader::_simdjson_set_column_value(this=0x00007f9433b9a180, value=0x00007f96db7721f8, block=0x00007f97c81a8ce8, slot_descs=size=4, valid=0x00007f96db7721ef) at new_json_reader.cpp:935:13
    frame #1: 0x0000556a4b1234c4 doris_be`doris::vectorized::NewJsonReader::_simdjson_handle_simple_json_write_columns(this=0x00007f9433b9a180, block=0x00007f97c81a8ce8, slot_descs=size=4, is_empty_row=0x00007f96db7723ef, eof=0x00007f9433b9a388) at new_json_reader.cpp:705:17
    frame #2: 0x0000556a4b11ffea doris_be`doris::vectorized::NewJsonReader::_simdjson_handle_simple_json(this=0x00007f9433b9a180, (null)=0x00007f953b52ba00, block=0x00007f97c81a8ce8, slot_descs=size=4, is_empty_row=0x00007f96db7723ef, eof=0x00007f9433b9a388) at new_json_reader.cpp:668:9
    frame #3: 0x0000556a4b11e737 doris_be`doris::vectorized::NewJsonReader::_read_json_column(this=0x00007f9433b9a180, state=0x00007f953b52ba00, block=0x00007f97c81a8ce8, slot_descs=size=4, is_empty_row=0x00007f96db7723ef, eof=0x00007f9433b9a388) at new_json_reader.cpp:502:12
    frame #4: 0x0000556a4b11bcee doris_be`doris::vectorized::NewJsonReader::get_next_block(this=0x00007f9433b9a180, block=0x00007f97c81a8ce8, read_rows=0x00007f96db7724b8, eof=0x00007f97c81a8a30) at new_json_reader.cpp:217:9
    frame #5: 0x0000556a4b60e080 doris_be`doris::vectorized::FileScanner::_get_block_wrapped(this=0x00007f97c81a8000, state=0x00007f953b52ba00, block=0x00007f978f75cfe0, eof=0x00007f96db7730d7) at file_scanner.cpp:465:13
    frame #6: 0x0000556a4b607e20 doris_be`doris::vectorized::FileScanner::_get_block_impl(this=0x00007f97c81a8000, state=0x00007f953b52ba00, block=0x00007f978f75cfe0, eof=0x00007f96db7730d7) at file_scanner.cpp:402:17
    frame #7: 0x0000556a4b6eeaab doris_be`doris::vectorized::Scanner::get_block(this=0x00007f97c81a8000, state=0x00007f953b52ba00, block=0x00007f978f75cfe0, eof=0x00007f96db7730d7) at scanner.cpp:143:17
    frame #8: 0x0000556a4b6ee67e doris_be`doris::vectorized::Scanner::get_block_after_projects(this=0x00007f97c81a8000, state=0x00007f953b52ba00, block=0x00007f978f75cfe0, eos=0x00007f96db7730d7) at scanner.cpp:119:16
    frame #9: 0x0000556a4b6f67a3 doris_be`doris::vectorized::ScannerScheduler::_scanner_scan(ctx=std::__shared_ptr&amp;lt;doris::vectorized::ScannerContext, __gnu_cxx::_S_atomic&amp;gt;::element_type @ 0x00007f953b0f8210, scan_task=std::__shared_ptr&amp;lt;doris::vectorized::ScanTask, __gnu_cxx::_S_atomic&amp;gt;::element_type @ 0x00007f953b542290) at scanner_scheduler.cpp:177:5
    frame #10: 0x0000556a4b6f569d doris_be`doris::vectorized::ScannerScheduler::submit(this=0x00007f96db773620)::$_0::operator()() const::&apos;lambda&apos;()::operator()() const::&apos;lambda&apos;()::operator()() const at scanner_scheduler.cpp:75:17
    frame #11: 0x0000556a4b6f54b7 doris_be`doris::vectorized::ScannerScheduler::submit(this=0x00007f97cafd0300)::$_0::operator()() const::&apos;lambda&apos;()::operator()() const at scanner_scheduler.cpp:74:27
    frame #12: 0x0000556a4b6f5475 doris_be`bool std::__invoke_impl&amp;lt;bool, doris::vectorized::ScannerScheduler::submit(std::shared_ptr&amp;lt;doris::vectorized::ScannerContext&amp;gt;, std::shared_ptr&amp;lt;doris::vectorized::ScanTask&amp;gt;)::$_0::operator()() const::&apos;lambda&apos;()&amp;amp;&amp;gt;((null)=__invoke_other @ 0x00007f96db77366f, __f=0x00007f97cafd0300) at invoke.h:61:14
    frame #13: 0x0000556a4b6f5435 doris_be`std::enable_if&amp;lt;is_invocable_r_v&amp;lt;bool, doris::vectorized::ScannerScheduler::submit(std::shared_ptr&amp;lt;doris::vectorized::ScannerContext&amp;gt;, std::shared_ptr&amp;lt;doris::vectorized::ScanTask&amp;gt;)::$_0::operator()() const::&apos;lambda&apos;()&amp;amp;&amp;gt;, bool&amp;gt;::type std::__invoke_r&amp;lt;bool, doris::vectorized::ScannerScheduler::submit(std::shared_ptr&amp;lt;doris::vectorized::ScannerContext&amp;gt;, std::shared_ptr&amp;lt;doris::vectorized::ScanTask&amp;gt;)::$_0::operator()() const::&apos;lambda&apos;()&amp;amp;&amp;gt;(__fn=0x00007f97cafd0300) at invoke.h:114:9
    frame #14: 0x0000556a4b6f52ed doris_be`std::_Function_handler&amp;lt;bool (), doris::vectorized::ScannerScheduler::submit(std::shared_ptr&amp;lt;doris::vectorized::ScannerContext&amp;gt;, std::shared_ptr&amp;lt;doris::vectorized::ScanTask&amp;gt;)::$_0::operator()() const::&apos;lambda&apos;()&amp;gt;::_M_invoke(__functor=0x00007f97c8daab38) at std_function.h:290:9
    frame #15: 0x0000556a43737e1e doris_be`std::function&amp;lt;bool ()&amp;gt;::operator()(this=0x00007f97c8daab38) const at std_function.h:591:9
    frame #16: 0x0000556a4b6f4782 doris_be`doris::vectorized::ScannerSplitRunner::process_for(this=0x00007f97c8daab10, (null)=(__r = 1000000000)) at scanner_scheduler.cpp:414:25
    frame #17: 0x0000556a4b75987c doris_be`doris::vectorized::PrioritizedSplitRunner::process(this=0x00007f97ce996b90) at prioritized_split_runner.cpp:103:35
    frame #18: 0x0000556a4b73fac0 doris_be`doris::vectorized::TimeSharingTaskExecutor::_dispatch_thread(this=0x00007f97651fe810) at time_sharing_task_executor.cpp:566:77
    frame #19: 0x0000556a4b74e5c2 doris_be`void std::__invoke_impl&amp;lt;void, void (doris::vectorized::TimeSharingTaskExecutor::*&amp;amp;)(), doris::vectorized::TimeSharingTaskExecutor*&amp;amp;&amp;gt;((null)=__invoke_memfun_deref @ 0x00007f96db7746cf, __f=0x00007f978f80af80, __t=0x00007f978f80af90) at invoke.h:74:14
    frame #20: 0x0000556a4b74e50d doris_be`std::__invoke_result&amp;lt;void (doris::vectorized::TimeSharingTaskExecutor::*&amp;amp;)(), doris::vectorized::TimeSharingTaskExecutor*&amp;amp;&amp;gt;::type std::__invoke&amp;lt;void (doris::vectorized::TimeSharingTaskExecutor::*&amp;amp;)(), doris::vectorized::TimeSharingTaskExecutor*&amp;amp;&amp;gt;(__fn=0x00007f978f80af80, __args=0x00007f978f80af90) at invoke.h:96:14
    frame #21: 0x0000556a4b74e4dd doris_be`void std::_Bind&amp;lt;void (doris::vectorized::TimeSharingTaskExecutor::* (doris::vectorized::TimeSharingTaskExecutor*))()&amp;gt;::__call&amp;lt;void, 0ul&amp;gt;(this=0x00007f978f80af80, __args=0x00007f96db774767, (null)=_Index_tuple&amp;lt;0UL&amp;gt; @ 0x00007f96db77473f) at functional:513:11
    frame #22: 0x0000556a4b74e496 doris_be`void std::_Bind&amp;lt;void (doris::vectorized::TimeSharingTaskExecutor::* (doris::vectorized::TimeSharingTaskExecutor*))()&amp;gt;::operator()&amp;lt;void&amp;gt;(this=0x00007f978f80af80) at functional:598:17
    frame #23: 0x0000556a4b74e465 doris_be`void std::__invoke_impl&amp;lt;void, std::_Bind&amp;lt;void (doris::vectorized::TimeSharingTaskExecutor::* (doris::vectorized::TimeSharingTaskExecutor*))()&amp;gt;&amp;amp;&amp;gt;((null)=__invoke_other @ 0x00007f96db77478f, __f=0x00007f978f80af80) at invoke.h:61:14
    frame #24: 0x0000556a4b74e425 doris_be`std::enable_if&amp;lt;is_invocable_r_v&amp;lt;void, std::_Bind&amp;lt;void (doris::vectorized::TimeSharingTaskExecutor::* (doris::vectorized::TimeSharingTaskExecutor*))()&amp;gt;&amp;amp;&amp;gt;, void&amp;gt;::type std::__invoke_r&amp;lt;void, std::_Bind&amp;lt;void (doris::vectorized::TimeSharingTaskExecutor::* (doris::vectorized::TimeSharingTaskExecutor*))()&amp;gt;&amp;amp;&amp;gt;(__fn=0x00007f978f80af80) at invoke.h:111:2
    frame #25: 0x0000556a4b74e28d doris_be`std::_Function_handler&amp;lt;void (), std::_Bind&amp;lt;void (doris::vectorized::TimeSharingTaskExecutor::* (doris::vectorized::TimeSharingTaskExecutor*))()&amp;gt;&amp;gt;::_M_invoke(__functor=0x00007f978f821620) at std_function.h:290:9
    frame #26: 0x0000556a436da65e doris_be`std::function&amp;lt;void ()&amp;gt;::operator()(this=0x00007f978f821620) const at std_function.h:591:9
    frame #27: 0x0000556a4587d962 doris_be`doris::Thread::supervise_thread(arg=0x00007f978f821610) at thread.cpp:460:5
    frame #28: 0x00007f9898d66b7b libc.so.6`___lldb_unnamed_symbol3696 + 667
    frame #29: 0x00007f9898de47b8 libc.so.6`___lldb_unnamed_symbol4129 + 7


&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;消费者&lt;/h4&gt;
&lt;p&gt;下面是消费者的堆栈&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;* thread #519, name = &apos;brpc_heavy&apos;, stop reason = breakpoint 4.1
  * frame #0: 0x000055ad89c6a1e6 doris_be`doris::MemTable::insert(this=0x00007f62caea3600, input_block=0x00007f64cb71fe98, row_idxs=size=1) at memtable.cpp:199:5
    frame #1: 0x000055ad89cacc15 doris_be`doris::MemTableWriter::write(this=0x00007f6579f88000, block=0x00007f64cb71fe98, row_idxs=size=1) at memtable_writer.cpp:118:27
    frame #2: 0x000055ad8a76e50b doris_be`doris::DeltaWriter::write(this=0x00007f6579f08e00, block=0x00007f64cb71fe98, row_idxs=size=1) at delta_writer.cpp:160:30
    frame #3: 0x000055ad8aad6744 doris_be`doris::BaseTabletsChannel::_write_block_data(doris::PTabletWriterAddBlockRequest const&amp;amp;, long, std::unordered_map&amp;lt;long, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;, std::hash&amp;lt;long&amp;gt;, std::equal_to&amp;lt;long&amp;gt;, std::allocator&amp;lt;std::pair&amp;lt;long const, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;amp;, doris::PTabletWriterAddBlockResult*)::$_0::operator()(this=0x00007f64cb71fd60, writer=0x00007f6579f08e00) const at tablets_channel.cpp:619:9
    frame #4: 0x000055ad8aad66fb doris_be`doris::Status std::__invoke_impl&amp;lt;doris::Status, doris::BaseTabletsChannel::_write_block_data(doris::PTabletWriterAddBlockRequest const&amp;amp;, long, std::unordered_map&amp;lt;long, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;, std::hash&amp;lt;long&amp;gt;, std::equal_to&amp;lt;long&amp;gt;, std::allocator&amp;lt;std::pair&amp;lt;long const, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;amp;, doris::PTabletWriterAddBlockResult*)::$_0&amp;amp;, doris::BaseDeltaWriter*&amp;gt;((null)=__invoke_other @ 0x00007f64cb71f927, __f=0x00007f64cb71fd60, __args=0x00007f64cb71f9d8) at invoke.h:61:14
    frame #5: 0x000055ad8aad6688 doris_be`std::enable_if&amp;lt;is_invocable_r_v&amp;lt;doris::Status, doris::BaseTabletsChannel::_write_block_data(doris::PTabletWriterAddBlockRequest const&amp;amp;, long, std::unordered_map&amp;lt;long, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;, std::hash&amp;lt;long&amp;gt;, std::equal_to&amp;lt;long&amp;gt;, std::allocator&amp;lt;std::pair&amp;lt;long const, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;amp;, doris::PTabletWriterAddBlockResult*)::$_0&amp;amp;, doris::BaseDeltaWriter*&amp;gt;, doris::Status&amp;gt;::type std::__invoke_r&amp;lt;doris::Status, doris::BaseTabletsChannel::_write_block_data(doris::PTabletWriterAddBlockRequest const&amp;amp;, long, std::unordered_map&amp;lt;long, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;, std::hash&amp;lt;long&amp;gt;, std::equal_to&amp;lt;long&amp;gt;, std::allocator&amp;lt;std::pair&amp;lt;long const, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;amp;, doris::PTabletWriterAddBlockResult*)::$_0&amp;amp;, doris::BaseDeltaWriter*&amp;gt;(__fn=0x00007f64cb71fd60, __args=0x00007f64cb71f9d8) at invoke.h:114:9
    frame #6: 0x000055ad8aad6588 doris_be`std::_Function_handler&amp;lt;doris::Status (doris::BaseDeltaWriter*), doris::BaseTabletsChannel::_write_block_data(doris::PTabletWriterAddBlockRequest const&amp;amp;, long, std::unordered_map&amp;lt;long, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;, std::hash&amp;lt;long&amp;gt;, std::equal_to&amp;lt;long&amp;gt;, std::allocator&amp;lt;std::pair&amp;lt;long const, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;amp;, doris::PTabletWriterAddBlockResult*)::$_0&amp;gt;::_M_invoke(__functor=0x00007f64cb71fd60, __args=0x00007f64cb71f9d8) at std_function.h:290:9
    frame #7: 0x000055ad8aae0b59 doris_be`std::function&amp;lt;doris::Status (doris::BaseDeltaWriter*)&amp;gt;::operator()(this=0x00007f64cb71fd60, __args=0x00007f6579f08e00) const at std_function.h:591:9
    frame #8: 0x000055ad8aad5ca5 doris_be`doris::BaseTabletsChannel::_write_block_data(doris::PTabletWriterAddBlockRequest const&amp;amp;, long, std::unordered_map&amp;lt;long, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;, std::hash&amp;lt;long&amp;gt;, std::equal_to&amp;lt;long&amp;gt;, std::allocator&amp;lt;std::pair&amp;lt;long const, std::vector&amp;lt;unsigned int, doris::CustomStdAllocator&amp;lt;unsigned int, doris::Allocator&amp;lt;false, false, false, doris::DefaultMemoryAllocator, true&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;amp;, doris::PTabletWriterAddBlockResult*)::$_2::operator()(this=0x00007f64cb71fde0, tablet_id=1772371123463, write_func=function&amp;lt;doris::Status (doris::BaseDeltaWriter *)&amp;gt; @ 0x00007f64cb71fd60) const at tablets_channel.cpp:599:21
    frame #9: 0x000055ad8aad5855 doris_be`doris::BaseTabletsChannel::_write_block_data(this=0x00007f6579d54b10, request=0x00007f631fa65d00, cur_seq=0, tablet_to_rowidxs=size=1, response=0x00007f61bef4f9c0) at tablets_channel.cpp:619:9
    frame #10: 0x000055ad8aad05ad doris_be`doris::TabletsChannel::add_batch(this=0x00007f6579d54b10, request=0x00007f631fa65d00, response=0x00007f61bef4f9c0) at tablets_channel.cpp:657:12
    frame #11: 0x000055ad8a919e7c doris_be`doris::LoadChannel::add_batch(this=0x00007f6579c1a600, request=0x00007f631fa65d00, response=0x00007f61bef4f9c0) at load_channel.cpp:195:9
    frame #12: 0x000055ad8a90e6c1 doris_be`doris::LoadChannelMgr::add_batch(this=0x00007f65e4f0d280, request=0x00007f631fa65d00, response=0x00007f61bef4f9c0) at load_channel_mgr.cpp:178:26
    frame #13: 0x000055ad8ac5dc47 doris_be`doris::PInternalService::tablet_writer_add_block(google::protobuf::RpcController*, doris::PTabletWriterAddBlockRequest const*, doris::PTabletWriterAddBlockResult*, google::protobuf::Closure*)::$_0::operator()(this=0x00007f65e2726640) const at internal_service.cpp:502:54
    frame #14: 0x000055ad8ac5db85 doris_be`void std::__invoke_impl&amp;lt;void, doris::PInternalService::tablet_writer_add_block(google::protobuf::RpcController*, doris::PTabletWriterAddBlockRequest const*, doris::PTabletWriterAddBlockResult*, google::protobuf::Closure*)::$_0&amp;amp;&amp;gt;((null)=__invoke_other @ 0x00007f64cb72057f, __f=0x00007f65e2726640) at invoke.h:61:14
    frame #15: 0x000055ad8ac5db45 doris_be`std::enable_if&amp;lt;is_invocable_r_v&amp;lt;void, doris::PInternalService::tablet_writer_add_block(google::protobuf::RpcController*, doris::PTabletWriterAddBlockRequest const*, doris::PTabletWriterAddBlockResult*, google::protobuf::Closure*)::$_0&amp;amp;&amp;gt;, void&amp;gt;::type std::__invoke_r&amp;lt;void, doris::PInternalService::tablet_writer_add_block(google::protobuf::RpcController*, doris::PTabletWriterAddBlockRequest const*, doris::PTabletWriterAddBlockResult*, google::protobuf::Closure*)::$_0&amp;amp;&amp;gt;(__fn=0x00007f65e2726640) at invoke.h:111:2
    frame #16: 0x000055ad8ac5da2d doris_be`std::_Function_handler&amp;lt;void (), doris::PInternalService::tablet_writer_add_block(google::protobuf::RpcController*, doris::PTabletWriterAddBlockRequest const*, doris::PTabletWriterAddBlockResult*, google::protobuf::Closure*)::$_0&amp;gt;::_M_invoke(__functor=0x00007f64cb7206d0) at std_function.h:290:9
    frame #17: 0x000055ad88d2265e doris_be`std::function&amp;lt;void ()&amp;gt;::operator()(this=0x00007f64cb7206d0) const at std_function.h:591:9
    frame #18: 0x000055ad8ac7e6e2 doris_be`doris::WorkThreadPool&amp;lt;false&amp;gt;::work_thread(this=0x00007f658ae2ac10, thread_id=1) at work_thread_pool.hpp:159:17
    frame #19: 0x000055ad8ac7f1cc doris_be`void std::__invoke_impl&amp;lt;void, void (doris::WorkThreadPool&amp;lt;false&amp;gt;::* const&amp;amp;)(int), doris::WorkThreadPool&amp;lt;false&amp;gt;*&amp;amp;, int&amp;amp;&amp;gt;((null)=__invoke_memfun_deref @ 0x00007f64cb7207df, __f=0x00007f658108b2a8, __t=0x00007f658108b2c0, __args=0x00007f658108b2b8) at invoke.h:74:14
    frame #20: 0x000055ad8ac7f155 doris_be`std::__invoke_result&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::* const&amp;amp;)(int), doris::WorkThreadPool&amp;lt;false&amp;gt;*&amp;amp;, int&amp;amp;&amp;gt;::type std::__invoke&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::* const&amp;amp;)(int), doris::WorkThreadPool&amp;lt;false&amp;gt;*&amp;amp;, int&amp;amp;&amp;gt;(__fn=0x00007f658108b2a8, __args=0x00007f658108b2c0, __args=0x00007f658108b2b8) at invoke.h:96:14
    frame #21: 0x000055ad8ac7f125 doris_be`decltype(std::__invoke((*this)._M_pmf, std::forward&amp;lt;doris::WorkThreadPool&amp;lt;false&amp;gt;*&amp;amp;&amp;gt;(fp), std::forward&amp;lt;int&amp;amp;&amp;gt;(fp))) std::_Mem_fn_base&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int), true&amp;gt;::operator()&amp;lt;doris::WorkThreadPool&amp;lt;false&amp;gt;*&amp;amp;, int&amp;amp;&amp;gt;(this=0x00007f658108b2a8, __args=0x00007f658108b2c0, __args=0x00007f658108b2b8) const at functional:177:11
    frame #22: 0x000055ad8ac7f0f5 doris_be`void std::__invoke_impl&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt;&amp;amp;, doris::WorkThreadPool&amp;lt;false&amp;gt;*&amp;amp;, int&amp;amp;&amp;gt;((null)=__invoke_other @ 0x00007f64cb72086f, __f=0x00007f658108b2a8, __args=0x00007f658108b2c0, __args=0x00007f658108b2b8) at invoke.h:61:14
    frame #23: 0x000055ad8ac7f065 doris_be`std::enable_if&amp;lt;is_invocable_r_v&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt;&amp;amp;, doris::WorkThreadPool&amp;lt;false&amp;gt;*&amp;amp;, int&amp;amp;&amp;gt;, void&amp;gt;::type std::__invoke_r&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt;&amp;amp;, doris::WorkThreadPool&amp;lt;false&amp;gt;*&amp;amp;, int&amp;amp;&amp;gt;(__fn=0x00007f658108b2a8, __args=0x00007f658108b2c0, __args=0x00007f658108b2b8) at invoke.h:111:2
    frame #24: 0x000055ad8ac7f032 doris_be`void std::_Bind_result&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt; (doris::WorkThreadPool&amp;lt;false&amp;gt;*, int)&amp;gt;::__call&amp;lt;void, 0ul, 1ul&amp;gt;(this=0x00007f658108b2a8, __args=0x00007f64cb720907, (null)=_Index_tuple&amp;lt;0UL, 1UL&amp;gt; @ 0x00007f64cb7208df) at functional:661:11
    frame #25: 0x000055ad8ac7efc6 doris_be`void std::_Bind_result&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt; (doris::WorkThreadPool&amp;lt;false&amp;gt;*, int)&amp;gt;::operator()&amp;lt;&amp;gt;(this=0x00007f658108b2a8) at functional:720:17
    frame #26: 0x000055ad8ac7ef95 doris_be`void std::__invoke_impl&amp;lt;void, std::_Bind_result&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt; (doris::WorkThreadPool&amp;lt;false&amp;gt;*, int)&amp;gt;&amp;gt;((null)=__invoke_other @ 0x00007f64cb72092f, __f=0x00007f658108b2a8) at invoke.h:61:14
    frame #27: 0x000055ad8ac7ef55 doris_be`std::__invoke_result&amp;lt;std::_Bind_result&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt; (doris::WorkThreadPool&amp;lt;false&amp;gt;*, int)&amp;gt;&amp;gt;::type std::__invoke&amp;lt;std::_Bind_result&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt; (doris::WorkThreadPool&amp;lt;false&amp;gt;*, int)&amp;gt;&amp;gt;(__fn=0x00007f658108b2a8) at invoke.h:96:14
    frame #28: 0x000055ad8ac7ef2d doris_be`void std::thread::_Invoker&amp;lt;std::tuple&amp;lt;std::_Bind_result&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt; (doris::WorkThreadPool&amp;lt;false&amp;gt;*, int)&amp;gt;&amp;gt;&amp;gt;::_M_invoke&amp;lt;0ul&amp;gt;(this=0x00007f658108b2a8, (null)=_Index_tuple&amp;lt;0UL&amp;gt; @ 0x00007f64cb72096f) at std_thread.h:301:13
    frame #29: 0x000055ad8ac7ef05 doris_be`std::thread::_Invoker&amp;lt;std::tuple&amp;lt;std::_Bind_result&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt; (doris::WorkThreadPool&amp;lt;false&amp;gt;*, int)&amp;gt;&amp;gt;&amp;gt;::operator()(this=0x00007f658108b2a8) at std_thread.h:308:11
    frame #30: 0x000055ad8ac7ee49 doris_be`std::thread::_State_impl&amp;lt;std::thread::_Invoker&amp;lt;std::tuple&amp;lt;std::_Bind_result&amp;lt;void, std::_Mem_fn&amp;lt;void (doris::WorkThreadPool&amp;lt;false&amp;gt;::*)(int)&amp;gt; (doris::WorkThreadPool&amp;lt;false&amp;gt;*, int)&amp;gt;&amp;gt;&amp;gt;&amp;gt;::_M_run(this=0x00007f658108b2a0) at std_thread.h:253:13
    frame #31: 0x00007f66b50e1224 libstdc++.so.6`___lldb_unnamed_symbol8036 + 20
    frame #32: 0x00007f66b4d66b7b libc.so.6`___lldb_unnamed_symbol3696 + 667
    frame #33: 0x00007f66b4de47b8 libc.so.6`___lldb_unnamed_symbol4129 + 7


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果memtable满了之后会推到线程池然后&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void FlushToken::_flush_memtable(std::shared_ptr&amp;lt;MemTable&amp;gt; memtable_ptr, int32_t segment_id,
                                 int64_t submit_task_time) {
    signal::set_signal_task_id(_rowset_writer-&amp;gt;load_id());
    signal::tablet_id = memtable_ptr-&amp;gt;tablet_id();
    Defer defer {[&amp;amp;]() {
        std::lock_guard&amp;lt;std::mutex&amp;gt; lock(_mutex);
        _stats.flush_submit_count--;
        if (_stats.flush_submit_count == 0) {
            _submit_task_finish_cond.notify_one();
        }
        _stats.flush_running_count--;
        if (_stats.flush_running_count == 0) {
            _running_task_finish_cond.notify_one();
        }
    }};
    DBUG_EXECUTE_IF(&quot;FlushToken.flush_memtable.wait_before_first_shutdown&quot;,
                    { std::this_thread::sleep_for(std::chrono::milliseconds(10 * 1000)); });
    if (_is_shutdown()) {
        return;
    }
    DBUG_EXECUTE_IF(&quot;FlushToken.flush_memtable.wait_after_first_shutdown&quot;,
                    { std::this_thread::sleep_for(std::chrono::milliseconds(10 * 1000)); });
    _stats.flush_running_count++;
    // double check if shutdown to avoid wait running task finish count not accurate
    if (_is_shutdown()) {
        return;
    }
    DBUG_EXECUTE_IF(&quot;FlushToken.flush_memtable.wait_after_second_shutdown&quot;,
                    { std::this_thread::sleep_for(std::chrono::milliseconds(10 * 1000)); });
    uint64_t flush_wait_time_ns = MonotonicNanos() - submit_task_time;
    _stats.flush_wait_time_ns += flush_wait_time_ns;
    // If previous flush has failed, return directly
    {
        std::shared_lock rdlk(_flush_status_lock);
        if (!_flush_status.ok()) {
            return;
        }
    }

    MonotonicStopWatch timer;
    timer.start();
    size_t memory_usage = memtable_ptr-&amp;gt;memory_usage();

    int64_t flush_size;
    Status s = _do_flush_memtable(memtable_ptr.get(), segment_id, &amp;amp;flush_size);

    {
        std::shared_lock rdlk(_flush_status_lock);
        if (!_flush_status.ok()) {
            return;
        }
    }
    if (!s.ok()) {
        std::lock_guard wrlk(_flush_status_lock);
        LOG(WARNING) &amp;lt;&amp;lt; &quot;Flush memtable failed with res = &quot; &amp;lt;&amp;lt; s
                     &amp;lt;&amp;lt; &quot;, load_id: &quot; &amp;lt;&amp;lt; print_id(_rowset_writer-&amp;gt;load_id());
        _flush_status = s;
        return;
    }

    VLOG_CRITICAL &amp;lt;&amp;lt; &quot;flush memtable wait time: &quot;
                  &amp;lt;&amp;lt; PrettyPrinter::print(flush_wait_time_ns, TUnit::TIME_NS)
                  &amp;lt;&amp;lt; &quot;, flush memtable cost: &quot;
                  &amp;lt;&amp;lt; PrettyPrinter::print(timer.elapsed_time(), TUnit::TIME_NS)
                  &amp;lt;&amp;lt; &quot;, submit count: &quot; &amp;lt;&amp;lt; _stats.flush_submit_count
                  &amp;lt;&amp;lt; &quot;, running count: &quot; &amp;lt;&amp;lt; _stats.flush_running_count
                  &amp;lt;&amp;lt; &quot;, finish count: &quot; &amp;lt;&amp;lt; _stats.flush_finish_count
                  &amp;lt;&amp;lt; &quot;, mem size: &quot; &amp;lt;&amp;lt; PrettyPrinter::print_bytes(memory_usage)
                  &amp;lt;&amp;lt; &quot;, disk size: &quot; &amp;lt;&amp;lt; PrettyPrinter::print_bytes(flush_size);
    _stats.flush_time_ns += timer.elapsed_time();
    _stats.flush_finish_count++;
    _stats.flush_size_bytes += memtable_ptr-&amp;gt;memory_usage();
    _stats.flush_disk_size_bytes += flush_size;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;线程池的task最后执行的是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class MemtableFlushTask final : public Runnable {
    ENABLE_FACTORY_CREATOR(MemtableFlushTask);

public:
    MemtableFlushTask(std::shared_ptr&amp;lt;FlushToken&amp;gt; flush_token, std::shared_ptr&amp;lt;MemTable&amp;gt; memtable,
                      int32_t segment_id, int64_t submit_task_time)
            : _flush_token(flush_token),
              _memtable(memtable),
              _segment_id(segment_id),
              _submit_task_time(submit_task_time) {
        g_flush_task_num &amp;lt;&amp;lt; 1;
    }

    ~MemtableFlushTask() override { g_flush_task_num &amp;lt;&amp;lt; -1; }

    void run() override {
        auto token = _flush_token.lock();
        if (token) {
            token-&amp;gt;_flush_memtable(_memtable, _segment_id, _submit_task_time); // 核心代码
        } else {
            LOG(WARNING) &amp;lt;&amp;lt; &quot;flush token is deconstructed, ignore the flush task&quot;;
        }
    }

private:
    std::weak_ptr&amp;lt;FlushToken&amp;gt; _flush_token;
    std::shared_ptr&amp;lt;MemTable&amp;gt; _memtable;
    int32_t _segment_id;
    int64_t _submit_task_time;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行的是&lt;code&gt;FlushToken::_do_flush_memtable&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void FlushToken::_flush_memtable(std::shared_ptr&amp;lt;MemTable&amp;gt; memtable_ptr, int32_t segment_id,
                                 int64_t submit_task_time) {
    signal::set_signal_task_id(_rowset_writer-&amp;gt;load_id());
    signal::tablet_id = memtable_ptr-&amp;gt;tablet_id();
    Defer defer {[&amp;amp;]() {
        std::lock_guard&amp;lt;std::mutex&amp;gt; lock(_mutex);
        _stats.flush_submit_count--;
        if (_stats.flush_submit_count == 0) {
            _submit_task_finish_cond.notify_one();
        }
        _stats.flush_running_count--;
        if (_stats.flush_running_count == 0) {
            _running_task_finish_cond.notify_one();
        }
    }};
    DBUG_EXECUTE_IF(&quot;FlushToken.flush_memtable.wait_before_first_shutdown&quot;,
                    { std::this_thread::sleep_for(std::chrono::milliseconds(10 * 1000)); });
    if (_is_shutdown()) {
        return;
    }
    DBUG_EXECUTE_IF(&quot;FlushToken.flush_memtable.wait_after_first_shutdown&quot;,
                    { std::this_thread::sleep_for(std::chrono::milliseconds(10 * 1000)); });
    _stats.flush_running_count++;
    // double check if shutdown to avoid wait running task finish count not accurate
    if (_is_shutdown()) {
        return;
    }
    DBUG_EXECUTE_IF(&quot;FlushToken.flush_memtable.wait_after_second_shutdown&quot;,
                    { std::this_thread::sleep_for(std::chrono::milliseconds(10 * 1000)); });
    uint64_t flush_wait_time_ns = MonotonicNanos() - submit_task_time;
    _stats.flush_wait_time_ns += flush_wait_time_ns;
    // If previous flush has failed, return directly
    {
        std::shared_lock rdlk(_flush_status_lock);
        if (!_flush_status.ok()) {
            return;
        }
    }

    MonotonicStopWatch timer;
    timer.start();
    size_t memory_usage = memtable_ptr-&amp;gt;memory_usage();

    int64_t flush_size;
    Status s = _do_flush_memtable(memtable_ptr.get(), segment_id, &amp;amp;flush_size);

    {
        std::shared_lock rdlk(_flush_status_lock);
        if (!_flush_status.ok()) {
            return;
        }
    }
    if (!s.ok()) {
        std::lock_guard wrlk(_flush_status_lock);
        LOG(WARNING) &amp;lt;&amp;lt; &quot;Flush memtable failed with res = &quot; &amp;lt;&amp;lt; s
                     &amp;lt;&amp;lt; &quot;, load_id: &quot; &amp;lt;&amp;lt; print_id(_rowset_writer-&amp;gt;load_id());
        _flush_status = s;
        return;
    }

    VLOG_CRITICAL &amp;lt;&amp;lt; &quot;flush memtable wait time: &quot;
                  &amp;lt;&amp;lt; PrettyPrinter::print(flush_wait_time_ns, TUnit::TIME_NS)
                  &amp;lt;&amp;lt; &quot;, flush memtable cost: &quot;
                  &amp;lt;&amp;lt; PrettyPrinter::print(timer.elapsed_time(), TUnit::TIME_NS)
                  &amp;lt;&amp;lt; &quot;, submit count: &quot; &amp;lt;&amp;lt; _stats.flush_submit_count
                  &amp;lt;&amp;lt; &quot;, running count: &quot; &amp;lt;&amp;lt; _stats.flush_running_count
                  &amp;lt;&amp;lt; &quot;, finish count: &quot; &amp;lt;&amp;lt; _stats.flush_finish_count
                  &amp;lt;&amp;lt; &quot;, mem size: &quot; &amp;lt;&amp;lt; PrettyPrinter::print_bytes(memory_usage)
                  &amp;lt;&amp;lt; &quot;, disk size: &quot; &amp;lt;&amp;lt; PrettyPrinter::print_bytes(flush_size);
    _stats.flush_time_ns += timer.elapsed_time();
    _stats.flush_finish_count++;
    _stats.flush_size_bytes += memtable_ptr-&amp;gt;memory_usage();
    _stats.flush_disk_size_bytes += flush_size;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后执行的是&lt;code&gt;FlushToken::_do_flush_memtable&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Status FlushToken::_do_flush_memtable(MemTable* memtable, int32_t segment_id, int64_t* flush_size) {
    VLOG_CRITICAL &amp;lt;&amp;lt; &quot;begin to flush memtable for tablet: &quot; &amp;lt;&amp;lt; memtable-&amp;gt;tablet_id()
                  &amp;lt;&amp;lt; &quot;, memsize: &quot; &amp;lt;&amp;lt; PrettyPrinter::print_bytes(memtable-&amp;gt;memory_usage())
                  &amp;lt;&amp;lt; &quot;, rows: &quot; &amp;lt;&amp;lt; memtable-&amp;gt;stat().raw_rows;
    memtable-&amp;gt;update_mem_type(MemType::FLUSH);
    int64_t duration_ns = 0;
    {
        SCOPED_RAW_TIMER(&amp;amp;duration_ns);
        SCOPED_ATTACH_TASK(memtable-&amp;gt;resource_ctx());
        SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(
                memtable-&amp;gt;resource_ctx()-&amp;gt;memory_context()-&amp;gt;mem_tracker()-&amp;gt;write_tracker());
        SCOPED_CONSUME_MEM_TRACKER(memtable-&amp;gt;mem_tracker());

        // DEFER_RELEASE_RESERVED();

        // auto reserve_size = memtable-&amp;gt;get_flush_reserve_memory_size();
        // if (memtable-&amp;gt;resource_ctx()-&amp;gt;task_controller()-&amp;gt;is_enable_reserve_memory() &amp;amp;&amp;amp;
        //     reserve_size &amp;gt; 0) {
        //     RETURN_IF_ERROR(_try_reserve_memory(memtable-&amp;gt;resource_ctx(), reserve_size));
        // }

        // Defer defer {[&amp;amp;]() {
        //     ExecEnv::GetInstance()-&amp;gt;storage_engine().memtable_flush_executor()-&amp;gt;dec_flushing_task();
        // }};
        std::unique_ptr&amp;lt;Block&amp;gt; block;
        RETURN_IF_ERROR(memtable-&amp;gt;to_block(&amp;amp;block));
        RETURN_IF_ERROR(_rowset_writer-&amp;gt;flush_memtable(block.get(), segment_id, flush_size));
        memtable-&amp;gt;set_flush_success();
    }
    _memtable_stat += memtable-&amp;gt;stat();
    DorisMetrics::instance()-&amp;gt;memtable_flush_total-&amp;gt;increment(1);
    DorisMetrics::instance()-&amp;gt;memtable_flush_duration_us-&amp;gt;increment(duration_ns / 1000);
    VLOG_CRITICAL &amp;lt;&amp;lt; &quot;after flush memtable for tablet: &quot; &amp;lt;&amp;lt; memtable-&amp;gt;tablet_id()
                  &amp;lt;&amp;lt; &quot;, flushsize: &quot; &amp;lt;&amp;lt; PrettyPrinter::print_bytes(*flush_size);
    return Status::OK();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Status FlushToken::_do_flush_memtable(MemTable* memtable, int32_t segment_id, int64_t* flush_size) {
    VLOG_CRITICAL &amp;lt;&amp;lt; &quot;begin to flush memtable for tablet: &quot; &amp;lt;&amp;lt; memtable-&amp;gt;tablet_id()
                  &amp;lt;&amp;lt; &quot;, memsize: &quot; &amp;lt;&amp;lt; PrettyPrinter::print_bytes(memtable-&amp;gt;memory_usage())
                  &amp;lt;&amp;lt; &quot;, rows: &quot; &amp;lt;&amp;lt; memtable-&amp;gt;stat().raw_rows;
    memtable-&amp;gt;update_mem_type(MemType::FLUSH);
    int64_t duration_ns = 0;
    {
        ... 
        RETURN_IF_ERROR(_rowset_writer-&amp;gt;flush_memtable(block.get(), segment_id, flush_size));
        ...
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们看看实现&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Status BetaRowsetWriterV2::flush_memtable(vectorized::Block* block, int32_t segment_id,
                                          int64_t* flush_size) {
    if (block-&amp;gt;rows() == 0) {
        return Status::OK();
    }

    {
        SCOPED_RAW_TIMER(&amp;amp;_segment_writer_ns);
        RETURN_IF_ERROR(_segment_creator.flush_single_block(block, segment_id, flush_size));
    }
    // delete bitmap and seg compaction are done on the destination BE.
    return Status::OK();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;void Tablet::add_rowsets(const std::vector&amp;lt;RowsetSharedPtr&amp;gt;&amp;amp; to_add) {
    if (to_add.empty()) {
        return;
    }
    std::vector&amp;lt;RowsetMetaSharedPtr&amp;gt; rs_metas;
    rs_metas.reserve(to_add.size());
    for (auto&amp;amp; rs : to_add) {
        _rs_version_map.emplace(rs-&amp;gt;version(), rs);
        _timestamped_version_tracker.add_version(rs-&amp;gt;version());
        rs_metas.push_back(rs-&amp;gt;rowset_meta());
    }
    _tablet_meta-&amp;gt;modify_rs_metas(rs_metas, {});
}

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Status BetaRowsetWriterV2::flush_memtable(vectorized::Block* block, int32_t segment_id,
                                          int64_t* flush_size) {
    if (block-&amp;gt;rows() == 0) {
        return Status::OK();
    }

    {
        SCOPED_RAW_TIMER(&amp;amp;_segment_writer_ns);
        RETURN_IF_ERROR(_segment_creator.flush_single_block(block, segment_id, flush_size));
    }
    // delete bitmap and seg compaction are done on the destination BE.
    return Status::OK();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;调用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Status SegmentFlusher::flush_single_block(const vectorized::Block* block, int32_t segment_id,
                                          int64_t* flush_size) {
    if (block-&amp;gt;rows() == 0) {
        return Status::OK();
    }
    vectorized::Block flush_block(*block);
    if (_context.write_type != DataWriteType::TYPE_COMPACTION &amp;amp;&amp;amp;
        _context.tablet_schema-&amp;gt;num_variant_columns() &amp;gt; 0) {
        RETURN_IF_ERROR(_parse_variant_columns(flush_block));
    }
    bool no_compression = flush_block.bytes() &amp;lt;= config::segment_compression_threshold_kb * 1024;
    if (config::enable_vertical_segment_writer) {
        std::unique_ptr&amp;lt;segment_v2::VerticalSegmentWriter&amp;gt; writer;
        RETURN_IF_ERROR(_create_segment_writer(writer, segment_id, no_compression));
        RETURN_IF_ERROR_OR_CATCH_EXCEPTION(_add_rows(writer, &amp;amp;flush_block, 0, flush_block.rows()));
        RETURN_IF_ERROR(_flush_segment_writer(writer, flush_size));
    } else {
        std::unique_ptr&amp;lt;segment_v2::SegmentWriter&amp;gt; writer;
        RETURN_IF_ERROR(_create_segment_writer(writer, segment_id, no_compression));
        RETURN_IF_ERROR_OR_CATCH_EXCEPTION(_add_rows(writer, &amp;amp;flush_block, 0, flush_block.rows()));
        RETURN_IF_ERROR(_flush_segment_writer(writer, flush_size));
    }
    return Status::OK();
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;后面调用&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Status SegmentWriter::append_block(const Block* block, size_t row_pos, size_t num_rows) {
    if (_opts.rowset_ctx-&amp;gt;partial_update_info &amp;amp;&amp;amp;
        _opts.rowset_ctx-&amp;gt;partial_update_info-&amp;gt;is_partial_update() &amp;amp;&amp;amp;
        _opts.write_type == DataWriteType::TYPE_DIRECT &amp;amp;&amp;amp;
        !_opts.rowset_ctx-&amp;gt;is_transient_rowset_writer) {
        if (_opts.rowset_ctx-&amp;gt;partial_update_info-&amp;gt;is_fixed_partial_update()) {
            RETURN_IF_ERROR(append_block_with_partial_content(block, row_pos, num_rows));
        } else {
            return Status::NotSupported&amp;lt;false&amp;gt;(
                    &quot;SegmentWriter doesn&apos;t support flexible partial update, please set &quot;
                    &quot;enable_vertical_segment_writer=true in be.conf on all BEs to use &quot;
                    &quot;VerticalSegmentWriter.&quot;);
        }
        return Status::OK();
    }
    if (block-&amp;gt;columns() &amp;lt; _column_writers.size()) {
        return Status::InternalError(
                &quot;block-&amp;gt;columns() &amp;lt; _column_writers.size(), block-&amp;gt;columns()=&quot; +
                std::to_string(block-&amp;gt;columns()) +
                &quot;, _column_writers.size()=&quot; + std::to_string(_column_writers.size()) +
                &quot;, _tablet_schema-&amp;gt;dump_structure()=&quot; + _tablet_schema-&amp;gt;dump_structure());
    }
    CHECK(block-&amp;gt;columns() &amp;gt;= _column_writers.size())
            &amp;lt;&amp;lt; &quot;, block-&amp;gt;columns()=&quot; &amp;lt;&amp;lt; block-&amp;gt;columns()
            &amp;lt;&amp;lt; &quot;, _column_writers.size()=&quot; &amp;lt;&amp;lt; _column_writers.size()
            &amp;lt;&amp;lt; &quot;, _tablet_schema-&amp;gt;dump_structure()=&quot; &amp;lt;&amp;lt; _tablet_schema-&amp;gt;dump_structure();
    // Row column should be filled here when it&apos;s a directly write from memtable
    // or it&apos;s schema change write(since column data type maybe changed, so we should reubild)
    if (_opts.write_type == DataWriteType::TYPE_DIRECT ||
        _opts.write_type == DataWriteType::TYPE_SCHEMA_CHANGE) {
        _serialize_block_to_row_column(*block);
    }

    if (_opts.rowset_ctx-&amp;gt;write_type != DataWriteType::TYPE_COMPACTION &amp;amp;&amp;amp;
        _tablet_schema-&amp;gt;num_variant_columns() &amp;gt; 0) {
        RETURN_IF_ERROR(variant_util::parse_and_materialize_variant_columns(
                const_cast&amp;lt;Block&amp;amp;&amp;gt;(*block), *_tablet_schema, _column_ids));
    }

    _olap_data_convertor-&amp;gt;set_source_content(block, row_pos, num_rows);

    // find all row pos for short key indexes
    std::vector&amp;lt;size_t&amp;gt; short_key_pos;
    if (_has_key) {
        // We build a short key index every `_opts.num_rows_per_block` rows. Specifically, we
        // build a short key index using 1st rows for first block and `_short_key_row_pos - _row_count`
        // for next blocks.
        // Ensure we build a short key index using 1st rows only for the first block (ISSUE-9766).
        if (UNLIKELY(_short_key_row_pos == 0 &amp;amp;&amp;amp; _num_rows_written == 0)) {
            short_key_pos.push_back(0);
        }
        while (_short_key_row_pos + _opts.num_rows_per_block &amp;lt; _num_rows_written + num_rows) {
            _short_key_row_pos += _opts.num_rows_per_block;
            short_key_pos.push_back(_short_key_row_pos - _num_rows_written);
        }
    }

    // convert column data from engine format to storage layer format
    std::vector&amp;lt;IOlapColumnDataAccessor*&amp;gt; key_columns;
    IOlapColumnDataAccessor* seq_column = nullptr;
    for (size_t id = 0; id &amp;lt; _column_writers.size(); ++id) {
        // olap data convertor alway start from id = 0
        auto converted_result = _olap_data_convertor-&amp;gt;convert_column_data(id);
        if (!converted_result.first.ok()) {
            return converted_result.first;
        }
        auto cid = _column_ids[id];
        if (_has_key &amp;amp;&amp;amp; cid &amp;lt; _tablet_schema-&amp;gt;num_key_columns()) {
            key_columns.push_back(converted_result.second);
        } else if (_has_key &amp;amp;&amp;amp; _tablet_schema-&amp;gt;has_sequence_col() &amp;amp;&amp;amp;
                   cid == _tablet_schema-&amp;gt;sequence_col_idx()) {
            seq_column = converted_result.second;
        }
        RETURN_IF_ERROR(_column_writers[id]-&amp;gt;append(converted_result.second-&amp;gt;get_nullmap(),
                                                    converted_result.second-&amp;gt;get_data(), num_rows));
    }
    if (_opts.write_type == DataWriteType::TYPE_COMPACTION) {
        RETURN_IF_ERROR(
                _variant_stats_calculator-&amp;gt;calculate_variant_stats(block, row_pos, num_rows));
    }
    if (_has_key) {
        if (_is_mow_with_cluster_key()) {
            // for now we don&apos;t need to query short key index for CLUSTER BY feature,
            // but we still write the index for future usage.
            // 1. generate primary key index, the key_columns is primary_key_columns
            RETURN_IF_ERROR(_generate_primary_key_index(_primary_key_coders, key_columns,
                                                        seq_column, num_rows, true));
            // 2. generate short key index (use cluster key)
            key_columns.clear();
            for (const auto&amp;amp; cid : _tablet_schema-&amp;gt;cluster_key_uids()) {
                // find cluster key index in tablet schema
                auto cluster_key_index = _tablet_schema-&amp;gt;field_index(cid);
                if (cluster_key_index == -1) {
                    return Status::InternalError(
                            &quot;could not find cluster key column with unique_id=&quot; +
                            std::to_string(cid) + &quot; in tablet schema&quot;);
                }
                bool found = false;
                for (auto i = 0; i &amp;lt; _column_ids.size(); ++i) {
                    if (_column_ids[i] == cluster_key_index) {
                        auto converted_result = _olap_data_convertor-&amp;gt;convert_column_data(i);
                        if (!converted_result.first.ok()) {
                            return converted_result.first;
                        }
                        key_columns.push_back(converted_result.second);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    return Status::InternalError(
                            &quot;could not found cluster key column with unique_id=&quot; +
                            std::to_string(cid) +
                            &quot;, tablet schema index=&quot; + std::to_string(cluster_key_index));
                }
            }
            RETURN_IF_ERROR(_generate_short_key_index(key_columns, num_rows, short_key_pos));
        } else if (_is_mow()) {
            RETURN_IF_ERROR(_generate_primary_key_index(_key_coders, key_columns, seq_column,
                                                        num_rows, false));
        } else {
            RETURN_IF_ERROR(_generate_short_key_index(key_columns, num_rows, short_key_pos));
        }
    }

    _num_rows_written += num_rows;
    _olap_data_convertor-&amp;gt;clear_source_content();
    return Status::OK();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;核心转换逻辑，将行转换成列：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;std::pair&amp;lt;Status, IOlapColumnDataAccessor*&amp;gt; OlapBlockDataConvertor::convert_column_data(
        size_t cid) {
    assert(cid &amp;lt; _convertors.size());
    auto convert_func = [&amp;amp;]() -&amp;gt; Status {
        RETURN_IF_ERROR_OR_CATCH_EXCEPTION(_convertors[cid]-&amp;gt;convert_to_olap());
        return Status::OK();
    };
    auto status = convert_func();
    return {status, _convertors[cid].get()};
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后segment 写入数据&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Status SegmentWriter::finalize(uint64_t* segment_file_size, uint64_t* index_size) {
    MonotonicStopWatch timer;
    timer.start();
    // check disk capacity
    if (_data_dir != nullptr &amp;amp;&amp;amp; _data_dir-&amp;gt;reach_capacity_limit((int64_t)estimate_segment_size())) {
        return Status::Error&amp;lt;DISK_REACH_CAPACITY_LIMIT&amp;gt;(&quot;disk {} exceed capacity limit, path: {}&quot;,
                                                        _data_dir-&amp;gt;path_hash(), _data_dir-&amp;gt;path());
    }
    // write data
    RETURN_IF_ERROR(finalize_columns_data());
    // Get the index start before finalize_footer since this function would write new data.
    uint64_t index_start = _file_writer-&amp;gt;bytes_appended();
    // write index
    RETURN_IF_ERROR(finalize_columns_index(index_size));
    // write footer
    RETURN_IF_ERROR(finalize_footer(segment_file_size));

    if (timer.elapsed_time() &amp;gt; 5000000000l) {
        LOG(INFO) &amp;lt;&amp;lt; &quot;segment flush consumes a lot time_ns &quot; &amp;lt;&amp;lt; timer.elapsed_time()
                  &amp;lt;&amp;lt; &quot;, segmemt_size &quot; &amp;lt;&amp;lt; *segment_file_size;
    }
    // When the cache type is not ttl(expiration time == 0), the data should be split into normal cache queue
    // and index cache queue
    if (auto* cache_builder = _file_writer-&amp;gt;cache_builder(); cache_builder != nullptr &amp;amp;&amp;amp;
                                                             cache_builder-&amp;gt;_expiration_time == 0 &amp;amp;&amp;amp;
                                                             config::is_cloud_mode()) {
        auto size = *index_size + *segment_file_size;
        auto holder = cache_builder-&amp;gt;allocate_cache_holder(index_start, size, _tablet-&amp;gt;tablet_id());
        for (auto&amp;amp; segment : holder-&amp;gt;file_blocks) {
            static_cast&amp;lt;void&amp;gt;(segment-&amp;gt;change_cache_type(io::FileCacheType::INDEX));
        }
    }
    return Status::OK();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际的堆栈：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;* thread #439, name = &apos;mf_normal [work&apos;, stop reason = breakpoint 2.1
  * frame #0: 0x000055ddfe4eaabc doris_be`doris::SegmentFlusher::flush_single_block(this=0x00007fbbbce0e450, block=0x00007fbc60901420, segment_id=0, flush_size=0x00007fbe639f4b50) at segment_creator.cpp:64:9
    frame #1: 0x000055ddfe4ef61a doris_be`doris::SegmentCreator::flush_single_block(this=0x00007fbbbce0e448, block=0x00007fbc60901420, segment_id=0, flush_size=0x00007fbe639f4b50) at segment_creator.cpp:404:5
    frame #2: 0x000055ddfe46a3c5 doris_be`doris::BaseBetaRowsetWriter::flush_memtable(this=0x00007fbbbce0e000, block=0x00007fbc60901420, segment_id=0, flush_size=0x00007fbe639f4b50) at beta_rowset_writer.cpp:817:9
    frame #3: 0x000055ddfe311da3 doris_be`doris::FlushToken::_do_flush_memtable(this=0x00007fbbbce22010, memtable=0x00007fbbbcce9200, segment_id=0, flush_size=0x00007fbe639f4b50) at memtable_flush_executor.cpp:210:9
    frame #4: 0x000055ddfe30fed4 doris_be`doris::FlushToken::_flush_memtable(this=0x00007fbbbce22010, memtable_ptr=std::__shared_ptr&amp;lt;doris::MemTable, __gnu_cxx::_S_atomic&amp;gt;::element_type @ 0x00007fbbbcce9200, segment_id=0, submit_task_time=120805632954059) at memtable_flush_executor.cpp:265:16
    frame #5: 0x000055ddfe3177b2 doris_be`doris::MemtableFlushTask::run(this=0x00007fbbbcdd70f0) at memtable_flush_executor.cpp:63:20
    frame #6: 0x000055ddff559fc8 doris_be`doris::ThreadPool::dispatch_thread(this=0x00007fbef9d2e980) at threadpool.cpp:616:24
    frame #7: 0x000055ddff568d42 doris_be`void std::__invoke_impl&amp;lt;void, void (doris::ThreadPool::*&amp;amp;)(), doris::ThreadPool*&amp;amp;&amp;gt;((null)=__invoke_memfun_deref @ 0x00007fbe639f56cf, __f=0x00007fbef9e46b20, __t=0x00007fbef9e46b30) at invoke.h:74:14
    frame #8: 0x000055ddff568c8d doris_be`std::__invoke_result&amp;lt;void (doris::ThreadPool::*&amp;amp;)(), doris::ThreadPool*&amp;amp;&amp;gt;::type std::__invoke&amp;lt;void (doris::ThreadPool::*&amp;amp;)(), doris::ThreadPool*&amp;amp;&amp;gt;(__fn=0x00007fbef9e46b20, __args=0x00007fbef9e46b30) at invoke.h:96:14
    frame #9: 0x000055ddff568c5d doris_be`void std::_Bind&amp;lt;void (doris::ThreadPool::* (doris::ThreadPool*))()&amp;gt;::__call&amp;lt;void, 0ul&amp;gt;(this=0x00007fbef9e46b20, __args=0x00007fbe639f5767, (null)=_Index_tuple&amp;lt;0UL&amp;gt; @ 0x00007fbe639f573f) at functional:513:11
    frame #10: 0x000055ddff568c16 doris_be`void std::_Bind&amp;lt;void (doris::ThreadPool::* (doris::ThreadPool*))()&amp;gt;::operator()&amp;lt;void&amp;gt;(this=0x00007fbef9e46b20) at functional:598:17
    frame #11: 0x000055ddff568be5 doris_be`void std::__invoke_impl&amp;lt;void, std::_Bind&amp;lt;void (doris::ThreadPool::* (doris::ThreadPool*))()&amp;gt;&amp;amp;&amp;gt;((null)=__invoke_other @ 0x00007fbe639f578f, __f=0x00007fbef9e46b20) at invoke.h:61:14
    frame #12: 0x000055ddff568ba5 doris_be`std::enable_if&amp;lt;is_invocable_r_v&amp;lt;void, std::_Bind&amp;lt;void (doris::ThreadPool::* (doris::ThreadPool*))()&amp;gt;&amp;amp;&amp;gt;, void&amp;gt;::type std::__invoke_r&amp;lt;void, std::_Bind&amp;lt;void (doris::ThreadPool::* (doris::ThreadPool*))()&amp;gt;&amp;amp;&amp;gt;(__fn=0x00007fbef9e46b20) at invoke.h:111:2
    frame #13: 0x000055ddff568a0d doris_be`std::_Function_handler&amp;lt;void (), std::_Bind&amp;lt;void (doris::ThreadPool::* (doris::ThreadPool*))()&amp;gt;&amp;gt;::_M_invoke(__functor=0x00007fbef9e4b520) at std_function.h:290:9
    frame #14: 0x000055ddfd3a265e doris_be`std::function&amp;lt;void ()&amp;gt;::operator()(this=0x00007fbef9e4b520) const at std_function.h:591:9
    frame #15: 0x000055ddff545962 doris_be`doris::Thread::supervise_thread(arg=0x00007fbef9e4b510) at thread.cpp:460:5
    frame #16: 0x00007fc02369db7b libc.so.6`___lldb_unnamed_symbol3696 + 667
    frame #17: 0x00007fc02371b7b8 libc.so.6`___lldb_unnamed_symbol4129 + 7
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;rowset/tablelet/segment/sst/row 关系&lt;/h2&gt;
&lt;p&gt;rowset/tablelet/segment和sst是什么关系呢？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tablet 包含多个rowset&lt;/li&gt;
&lt;li&gt;rowset是一次写入，一次写入包括一行或者多行&lt;/li&gt;
&lt;li&gt;一个rowset 包含一个或者多个segment&lt;/li&gt;
&lt;li&gt;segment 包括一行或者多行&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;相关阅读&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://doris.apache.org/zh-CN/community/design/doris_storage_optimization&quot;&gt;segment 格式&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://doris.apache.org/zh-CN/docs/3.x/admin-manual/system-tables/information_schema/rowsets&quot;&gt;rowset 和segment关系&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/SHWAITME/article/details/136155008&quot;&gt;rowset 和segment关系2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.itpub.net/70017904/viewspace-3003507/&quot;&gt;rowset和segment关系3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cloud.tencent.com/developer/article/1864333&quot;&gt;重新刷新doris&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Markdown Extended Features</title><link>https://tatamagic.com/posts/markdown-extended/</link><guid isPermaLink="true">https://tatamagic.com/posts/markdown-extended/</guid><description>Read more about Markdown features in Fuwari</description><pubDate>Wed, 01 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;GitHub Repository Cards&lt;/h2&gt;
&lt;p&gt;You can add dynamic cards that link to GitHub repositories, on page load, the repository information is pulled from the GitHub API.&lt;/p&gt;
&lt;p&gt;::github{repo=&quot;Fabrizz/MMM-OnSpotify&quot;}&lt;/p&gt;
&lt;p&gt;Create a GitHub repository card with the code &lt;code&gt;::github{repo=&quot;&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;&quot;}&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::github{repo=&quot;saicaca/fuwari&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Admonitions&lt;/h2&gt;
&lt;p&gt;Following types of admonitions are supported: &lt;code&gt;note&lt;/code&gt; &lt;code&gt;tip&lt;/code&gt; &lt;code&gt;important&lt;/code&gt; &lt;code&gt;warning&lt;/code&gt; &lt;code&gt;caution&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;:::note
Highlights information that users should take into account, even when skimming.
:::&lt;/p&gt;
&lt;p&gt;:::tip
Optional information to help a user be more successful.
:::&lt;/p&gt;
&lt;p&gt;:::important
Crucial information necessary for users to succeed.
:::&lt;/p&gt;
&lt;p&gt;:::warning
Critical content demanding immediate user attention due to potential risks.
:::&lt;/p&gt;
&lt;p&gt;:::caution
Negative potential consequences of an action.
:::&lt;/p&gt;
&lt;h3&gt;Basic Syntax&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;:::note
Highlights information that users should take into account, even when skimming.
:::

:::tip
Optional information to help a user be more successful.
:::
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Custom Titles&lt;/h3&gt;
&lt;p&gt;The title of the admonition can be customized.&lt;/p&gt;
&lt;p&gt;:::note[MY CUSTOM TITLE]
This is a note with a custom title.
:::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:::note[MY CUSTOM TITLE]
This is a note with a custom title.
:::
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;GitHub Syntax&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!TIP]
&lt;a href=&quot;https://github.com/orgs/community/discussions/16925&quot;&gt;The GitHub syntax&lt;/a&gt; is also supported.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; [!NOTE]
&amp;gt; The GitHub syntax is also supported.

&amp;gt; [!TIP]
&amp;gt; The GitHub syntax is also supported.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Spoiler&lt;/h3&gt;
&lt;p&gt;You can add spoilers to your text. The text also supports &lt;strong&gt;Markdown&lt;/strong&gt; syntax.&lt;/p&gt;
&lt;p&gt;The content :spoiler[is hidden &lt;strong&gt;ayyy&lt;/strong&gt;]!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The content :spoiler[is hidden **ayyy**]!

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Expressive Code Example</title><link>https://tatamagic.com/posts/expressive-code/</link><guid isPermaLink="true">https://tatamagic.com/posts/expressive-code/</guid><description>How code blocks look in Markdown using Expressive Code.</description><pubDate>Wed, 10 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Here, we&apos;ll explore how code blocks look using &lt;a href=&quot;https://expressive-code.com/&quot;&gt;Expressive Code&lt;/a&gt;. The provided examples are based on the official documentation, which you can refer to for further details.&lt;/p&gt;
&lt;h2&gt;Expressive Code&lt;/h2&gt;
&lt;h3&gt;Syntax Highlighting&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/syntax-highlighting/&quot;&gt;Syntax Highlighting&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Regular syntax highlighting&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;This code is syntax highlighted!&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Rendering ANSI escape sequences&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;ANSI colors:
- Regular: [31mRed[0m [32mGreen[0m [33mYellow[0m [34mBlue[0m [35mMagenta[0m [36mCyan[0m
- Bold:    [1;31mRed[0m [1;32mGreen[0m [1;33mYellow[0m [1;34mBlue[0m [1;35mMagenta[0m [1;36mCyan[0m
- Dimmed:  [2;31mRed[0m [2;32mGreen[0m [2;33mYellow[0m [2;34mBlue[0m [2;35mMagenta[0m [2;36mCyan[0m

256 colors (showing colors 160-177):
[38;5;160m160 [38;5;161m161 [38;5;162m162 [38;5;163m163 [38;5;164m164 [38;5;165m165[0m
[38;5;166m166 [38;5;167m167 [38;5;168m168 [38;5;169m169 [38;5;170m170 [38;5;171m171[0m
[38;5;172m172 [38;5;173m173 [38;5;174m174 [38;5;175m175 [38;5;176m176 [38;5;177m177[0m

Full RGB colors:
[38;2;34;139;34mForestGreen - RGB(34, 139, 34)[0m

Text formatting: [1mBold[0m [2mDimmed[0m [3mItalic[0m [4mUnderline[0m
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Editor &amp;amp; Terminal Frames&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/frames/&quot;&gt;Editor &amp;amp; Terminal Frames&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Code editor frames&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;Title attribute example&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- src/content/index.html --&amp;gt;
&amp;lt;div&amp;gt;File name comment example&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Terminal frames&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;This terminal frame has no title&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;Write-Output &quot;This one has a title!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Overriding frame types&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;Look ma, no frame!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;# Without overriding, this would be a terminal frame
function Watch-Tail { Get-Content -Tail 20 -Wait $args }
New-Alias tail Watch-Tail
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Text &amp;amp; Line Markers&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/text-markers/&quot;&gt;Text &amp;amp; Line Markers&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Marking full lines &amp;amp; line ranges&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Line 1 - targeted by line number
// Line 2
// Line 3
// Line 4 - targeted by line number
// Line 5
// Line 6
// Line 7 - targeted by range &quot;7-8&quot;
// Line 8 - targeted by range &quot;7-8&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Selecting line marker types (mark, ins, del)&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  console.log(&apos;this line is marked as deleted&apos;)
  // This line and the next one are marked as inserted
  console.log(&apos;this is the second inserted line&apos;)

  return &apos;this line uses the neutral default marker type&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Adding labels to line markers&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// labeled-line-markers.jsx
&amp;lt;button
  role=&quot;button&quot;
  {...props}
  value={value}
  className={buttonClassName}
  disabled={disabled}
  active={active}
&amp;gt;
  {children &amp;amp;&amp;amp;
    !active &amp;amp;&amp;amp;
    (typeof children === &apos;string&apos; ? &amp;lt;span&amp;gt;{children}&amp;lt;/span&amp;gt; : children)}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Adding long labels on their own lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// labeled-line-markers.jsx
&amp;lt;button
  role=&quot;button&quot;
  {...props}

  value={value}
  className={buttonClassName}

  disabled={disabled}
  active={active}
&amp;gt;

  {children &amp;amp;&amp;amp;
    !active &amp;amp;&amp;amp;
    (typeof children === &apos;string&apos; ? &amp;lt;span&amp;gt;{children}&amp;lt;/span&amp;gt; : children)}
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Using diff-like syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;+this line will be marked as inserted
-this line will be marked as deleted
this is a regular line
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+this is an actual diff file
-all contents will remain unmodified
 no whitespace will be removed either
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Combining syntax highlighting with diff-like syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;  function thisIsJavaScript() {
    // This entire block gets highlighted as JavaScript,
    // and we can still add diff markers to it!
-   console.log(&apos;Old code to be removed&apos;)
+   console.log(&apos;New and shiny code!&apos;)
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Marking individual text inside lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  // Mark any given text inside lines
  return &apos;Multiple matches of the given text are supported&apos;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Regular expressions&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;The words yes and yep will be marked.&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Escaping forward slashes&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;Test&quot; &amp;gt; /home/test.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Selecting inline marker types (mark, ins, del)&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;function demo() {
  console.log(&apos;These are inserted and deleted marker types&apos;);
  // The return statement uses the default marker type
  return true;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Word Wrap&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/key-features/word-wrap/&quot;&gt;Word Wrap&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Configuring word wrap per block&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Example with wrap
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Example with wrap=false
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Configuring indentation of wrapped lines&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Example with preserveIndent (enabled by default)
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Example with preserveIndent=false
function getLongString() {
  return &apos;This is a very long string that will most probably not fit into the available space unless the container is extremely wide&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Collapsible Sections&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/plugins/collapsible-sections/&quot;&gt;Collapsible Sections&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// All this boilerplate setup code will be collapsed
import { someBoilerplateEngine } from &apos;@example/some-boilerplate&apos;
import { evenMoreBoilerplate } from &apos;@example/even-more-boilerplate&apos;

const engine = someBoilerplateEngine(evenMoreBoilerplate())

// This part of the code will be visible by default
engine.doSomething(1, 2, 3, calcFn)

function calcFn() {
  // You can have multiple collapsed sections
  const a = 1
  const b = 2
  const c = a + b

  // This will remain visible
  console.log(`Calculation result: ${a} + ${b} = ${c}`)
  return c
}

// All this code until the end of the block will be collapsed again
engine.closeConnection()
engine.freeMemory()
engine.shutdown({ reason: &apos;End of example boilerplate code&apos; })
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Line Numbers&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://expressive-code.com/plugins/line-numbers/&quot;&gt;Line Numbers&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Displaying line numbers per block&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// This code block will show line numbers
console.log(&apos;Greetings from line 2!&apos;)
console.log(&apos;I am on line 3&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;pre&gt;&lt;code&gt;// Line numbers are disabled for this block
console.log(&apos;Hello?&apos;)
console.log(&apos;Sorry, do you know what line I am on?&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Changing the starting line number&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;console.log(&apos;Greetings from line 5!&apos;)
console.log(&apos;I am on line 6&apos;)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Simple Guides for Fuwari</title><link>https://tatamagic.com/posts/guide/</link><guid isPermaLink="true">https://tatamagic.com/posts/guide/</guid><description>How to use this blog template.</description><pubDate>Mon, 01 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Cover image source: &lt;a href=&quot;https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/208fc754-890d-4adb-9753-2c963332675d/width=2048/01651-1456859105-(colour_1.5),girl,_Blue,yellow,green,cyan,purple,red,pink,_best,8k,UHD,masterpiece,male%20focus,%201boy,gloves,%20ponytail,%20long%20hair,.jpeg&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This blog template is built with &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;. For the things that are not mentioned in this guide, you may find the answers in the &lt;a href=&quot;https://docs.astro.build/&quot;&gt;Astro Docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Front-matter of Posts&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;---
title: My First Blog Post
published: 2023-09-09
description: This is the first post of my new Astro blog.
image: ./cover.jpg
tags: [Foo, Bar]
category: Front-end
draft: false
---
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The title of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;published&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The date the post was published.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A short description of the post. Displayed on index page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The cover image path of the post.&amp;lt;br/&amp;gt;1. Start with &lt;code&gt;http://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt;: Use web image&amp;lt;br/&amp;gt;2. Start with &lt;code&gt;/&lt;/code&gt;: For image in &lt;code&gt;public&lt;/code&gt; dir&amp;lt;br/&amp;gt;3. With none of the prefixes: Relative to the markdown file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The tags of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;category&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The category of the post.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draft&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;If this post is still a draft, which won&apos;t be displayed.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Where to Place the Post Files&lt;/h2&gt;
&lt;p&gt;Your post files should be placed in &lt;code&gt;src/content/posts/&lt;/code&gt; directory. You can also create sub-directories to better organize your posts and assets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/
├── post-1.md
└── post-2/
    ├── cover.png
    └── index.md
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Markdown Example</title><link>https://tatamagic.com/posts/markdown/</link><guid isPermaLink="true">https://tatamagic.com/posts/markdown/</guid><description>A simple example of a Markdown blog post.</description><pubDate>Sun, 01 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;An h1 header&lt;/h1&gt;
&lt;p&gt;Paragraphs are separated by a blank line.&lt;/p&gt;
&lt;p&gt;2nd paragraph. &lt;em&gt;Italic&lt;/em&gt;, &lt;strong&gt;bold&lt;/strong&gt;, and &lt;code&gt;monospace&lt;/code&gt;. Itemized lists
look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this one&lt;/li&gt;
&lt;li&gt;that one&lt;/li&gt;
&lt;li&gt;the other one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that --- not considering the asterisk --- the actual text
content starts at 4-columns in.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Block quotes are
written like so.&lt;/p&gt;
&lt;p&gt;They can span multiple paragraphs,
if you like.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., &quot;it&apos;s all
in chapters 12--14&quot;). Three dots ... will be converted to an ellipsis.
Unicode is supported. ☺&lt;/p&gt;
&lt;h2&gt;An h2 header&lt;/h2&gt;
&lt;p&gt;Here&apos;s a numbered list:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;first item&lt;/li&gt;
&lt;li&gt;second item&lt;/li&gt;
&lt;li&gt;third item&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note again how the actual text starts at 4 columns in (4 characters
from the left side). Here&apos;s a code sample:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Let me re-iterate ...
for i in 1 .. 10 { do-something(i) }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you probably guessed, indented 4 spaces. By the way, instead of
indenting the block, you can use delimited blocks, if you like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;define foobar() {
    print &quot;Welcome to flavor country!&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(which makes copying &amp;amp; pasting easier). You can optionally mark the
delimited block for Pandoc to syntax highlight it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import time
# Quick, count to ten!
for i in range(10):
    # (but not *too* quick)
    time.sleep(0.5)
    print i
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;An h3 header&lt;/h3&gt;
&lt;p&gt;Now a nested list:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, get these ingredients:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;carrots&lt;/li&gt;
&lt;li&gt;celery&lt;/li&gt;
&lt;li&gt;lentils&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Boil some water.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dump everything in the pot and follow
this algorithm:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; find wooden spoon
 uncover pot
 stir
 cover pot
 balance wooden spoon precariously on pot handle
 wait 10 minutes
 goto first step (or shut off burner when done)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do not bump wooden spoon or it will fall.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notice again how text always lines up on 4-space indents (including
that last line which continues item 3 above).&lt;/p&gt;
&lt;p&gt;Here&apos;s a link to &lt;a href=&quot;http://foo.bar&quot;&gt;a website&lt;/a&gt;, to a &lt;a href=&quot;local-doc.html&quot;&gt;local
doc&lt;/a&gt;, and to a &lt;a href=&quot;#an-h2-header&quot;&gt;section heading in the current
doc&lt;/a&gt;. Here&apos;s a footnote [^1].&lt;/p&gt;
&lt;p&gt;[^1]: Footnote text goes here.&lt;/p&gt;
&lt;p&gt;Tables can look like this:&lt;/p&gt;
&lt;p&gt;size material color&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;9 leather brown
10 hemp canvas natural
11 glass transparent&lt;/p&gt;
&lt;p&gt;Table: Shoes, their sizes, and what they&apos;re made of&lt;/p&gt;
&lt;p&gt;(The above is the caption for the table.) Pandoc also supports
multi-line tables:&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;keyword text&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;red Sunsets, apples, and
other red or reddish
things.&lt;/p&gt;
&lt;p&gt;green Leaves, grass, frogs
and other things it&apos;s
not easy being.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;A horizontal rule follows.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Here&apos;s a definition list:&lt;/p&gt;
&lt;p&gt;apples
: Good for making applesauce.
oranges
: Citrus!
tomatoes
: There&apos;s no &quot;e&quot; in tomatoe.&lt;/p&gt;
&lt;p&gt;Again, text is indented 4 spaces. (Put a blank line between each
term/definition pair to spread things out more.)&lt;/p&gt;
&lt;p&gt;Here&apos;s a &quot;line block&quot;:&lt;/p&gt;
&lt;p&gt;| Line one
| Line too
| Line tree&lt;/p&gt;
&lt;p&gt;and images can be specified like so:&lt;/p&gt;
&lt;p&gt;Inline math equations go in like so: $\omega = d\phi / dt$. Display
math should get its own line and be put in in double-dollarsigns:&lt;/p&gt;
&lt;p&gt;$$I = \int \rho R^{2} dV$$&lt;/p&gt;
&lt;p&gt;$$
\begin{equation*}
\pi
=3.1415926535
;8979323846;2643383279;5028841971;6939937510;5820974944
;5923078164;0628620899;8628034825;3421170679;\ldots
\end{equation*}
$$&lt;/p&gt;
&lt;p&gt;And note that you can backslash-escape any punctuation characters
which you wish to be displayed literally, ex.: `foo`, *bar*, etc.&lt;/p&gt;
</content:encoded></item><item><title>Include Video in the Posts</title><link>https://tatamagic.com/posts/video/</link><guid isPermaLink="true">https://tatamagic.com/posts/video/</guid><description>This post demonstrates how to include embedded video in a blog post.</description><pubDate>Tue, 01 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just copy the embed code from YouTube or other platforms, and paste it in the markdown file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Include Video in the Post
published: 2023-10-19
// ...
---

&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;YouTube&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;https://www.youtube.com/embed/5gIf0_xpFPI?si=N1WTorLKL0uwLsU_&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;h2&gt;Bilibili&lt;/h2&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;468&quot; src=&quot;//player.bilibili.com/player.html?bvid=BV1fK4y1s7Qf&amp;amp;p=1&quot; scrolling=&quot;no&quot; border=&quot;0&quot; frameborder=&quot;no&quot; framespacing=&quot;0&quot; allowfullscreen=&quot;true&quot;&amp;gt; &amp;lt;/iframe&amp;gt;&lt;/p&gt;
</content:encoded></item></channel></rss>