202210

后台开发

微服务应用 API 设计规范
https://blog.jaggerwang.net/microservice-application-api-design-specification/

API 版本

  • 对于内部使用的 API,自己可以控制客户端升级节奏,应避免使用 API 版本,因为维护多版本 API 的成本很高。
  • 对于对外开放的 API,由于无法控制使用方客户端升级节奏,那么可以通过多版本 API 来实现平滑升级,在废弃老版 API 之前给使用方留足够的升级时间。
  • API 版本号可在不同的层级上添加,以前面的创建用户 API /api/user/user/create 为例,按作用范围由大到小有以下几种方式:

code

/api/v1/user/user/create 在应用网关层级添加(推荐);
/api/user/v1/user/create 在微服务层级添加;
/api/user/user/v1/create 在模块层级添加;
/api/user/user/create/v1 在 API 层级添加;

硬件

按下键盘后为什么屏幕上就会有输出
https://www.51cto.com/article/698488.html

内存中有这样一部分区域,是和显存映射的。啥意思,就是你往上图的这些内存区域中写数据,相当于写在了显存中。而往显存中写数据,就相当于在屏幕上输出文本了。

mov [0xB8000],'h' 
mov [0xB8002],'e' 
mov [0xB8004],'l' 
mov [0xB8006],'l' 
mov [0xB8008],'o' 

I2C接口与SPI和UART接口的区别
https://blog.csdn.net/chenhuanqiangnihao/article/details/123359352

总线接口 UART I2C SPI USB的异同点

  • UART(RS232) 通用异步串行口,速率不快,可全双工,结构上一般由波特率产生器、UART 发送器、UART 接收器组成,硬件上两线,一收一发。
  • SPI 高速同步串行口,高速,可全双工,收发独立,同步接口,可实现多个 SPI 设备互联,硬件 4 条线。
  • I2C 双向、两线、串行、多主控接口标准。速率不快,半双工,同步接口,具有总线仲裁机制,非常适合器件间近距离经常性数据通信,可实现设备组网。
  • USB 通用串行总线,高速,半双工,由主机、hub、设备组成。设备可以与下级 hub 相连构成星型结构。

OLED显示屏是利用有机电自发光二极管制成的显示屏,其中每一个像素点就是一个led。

ESP8266、ESP32和STM32的区别
https://baijiahao.baidu.com/s?id=1730615149655141528

  • ESP8266,价格 10 元左右。
  • ESP32,是 ESP8266 的升级版本,速度更快还带有蓝牙 4.2 和蓝牙低功耗,价格在20元左右
    • 优点:
      • ESP32 可用引脚比 ESP8266 更多
      • 双核处理器能够多线程实时处理;
      • 高速主频 240MHZ,对比 STM32F1 的 72MHZ 和 STM32F4 的168MHZ,速度快很多,价格 STM 系低出非常多;
      • 自带蓝牙和 Wifi,不用再花费成本去购置额外模块,成本更加低;
      • 编程上可以使用 arduino 环境,编程难度比 STM32 低很多,开源项目很多,开发速度很快。
    • 缺点:
      • 引脚数量过少是现阶段 ESP32 的硬伤之一
  • STM32 是一种基于ARM架构的32位微控制器。
    • 优点:
      • 通讯接口十分丰富,如 USART,I2C,SPI,CAN,以太网通讯等;
      • 可用 GPIO 数量非常多,可以控制大量设备;
      • 定时器数量很多,中断系统也十分完善,能实现非常复杂的逻辑;
      • 多路 ADC 和 DAC 功能,可用于读取大量传感器等;
      • 可运行 Free RTOS,RT thread,UCOS 等实时操作系统,可用于控制复杂系统;
      • 可连接 SD 卡,LCD 屏,有摄像头接口,可读取 USB 功能等。
    • 缺点:
      • STM32 的价格一直在上涨。如果不需要以太网、摄像头和 DACD 等功能时可以考虑 F1 系列。
      • 上手有一定难度,需要一定的时间。

前端

最简洁Vue+Electron项目搭建教程
https://zhuanlan.zhihu.com/p/335225253

vue3.x+ts项目创建,配置流程
https://blog.csdn.net/csl125/article/details/126000350

electron install

npm config set ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/
export ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/
npx electron-forge import
npm install --save-dev electron --registry=https://registry.npm.taobao.org
npm install --save-dev @electron-forge/cli --registry=https://registry.npm.taobao.org
npx electron-forge import
npm run make

electron-vite | 新一代electron开发构建工具
https://juejin.cn/post/7084126780390375461

├──src
|  ├──main
|  |  ├──index.js
|  |  └──...
|  ├──preload
|  |  ├──index.js
|  |  └──...
|  └──renderer
|     ├──src
|     ├──index.html
|     └──...
├──electron.vite.config.js
└──package.json

搭配 TypeScript 使用 Vue
https://cn.vuejs.org/guide/typescript/overview.html

深入理解 TypeScript
https://jkchao.github.io/typescript-book-chinese/#why

https://github.com/sindresorhus/electron-store
https://github.com/louischatriot/nedb

网络

iperf3-vsock: how to measure VSOCK performance
https://stefano-garzarella.github.io/posts/2019-08-22-vsock-iperf3/

Iperf3网络性能测试工具详解教程
https://www.cnblogs.com/xuanbjut/p/14144255.html

  • Iperf是美国伊利诺斯大学(University of Illinois)开发的一种开源的网络性能测试工具。可以用来测试网络节点间(也包括回环)TCP或UDP连接的性能,包括带宽、抖动以及丢包率,其中抖动和丢包率适应于UDP测试,而带宽测试适应于TCP和UDP。
  • Iperf是一款基于TCP/IP和UDP/IP的网络性能测试工具,可以用来测量网络带宽和网络质量,提供网络延迟抖动、数据包丢失率、最大传输单元等统计信息。网络管理员可以根据这些信息了解并判断网络性能问题,从而定位网络瓶颈,解决网络故障。

code

# server
iperf3 -s -i 1 -p 5200
# client
iperf -c 127.0.0.1 -i 1 -t 60 -p 5200

带宽测试通常采用UDP模式,因为能测出极限带宽、时延抖动、丢包率。在进行测试时,首先以链路理论带宽作为数据发送速率进行测试,例如,从客户端到服务器之间的链路的理论带宽为100Mbps,先用-b 100M进行测试,然后根据测试结果(包括实际带宽,时延抖动和丢包率),再以实际带宽作为数据发送速率进行测试,会发现时延抖动和丢包率比第一次好很多,重复测试几次,就能得出稳定的实际带宽。

# server
iperf3 -s -i 1 -p 5210
# client
iperf3 -u -c 127.0.0.1 -b 100m -t 10 -p 5210 -b 40G

TCP 和 UDP 可以使用同一个端口吗?
https://www.51cto.com/article/714728.html

linux

CPU内存乱序访问与内存屏障
https://blog.csdn.net/denglin12315/article/details/124488188

CPU内存乱序访问发生的原因

  • 编译优化,指令重排导致乱序
    • 编译器在编译代码时不感知多线程并发执行情况。
  • CPU运行,指令执行乱序
    • 在单核CPU 上,不考虑编译器优化导致乱序的前提下,多线程执行不存在内存乱序访问的问题。

什么时候用内存屏障

  • 单线程代码的程序不需要关心内存乱序的问题。
  • 在多线程编程中,由于使用互斥量,信号量已经隐式包含各种内存屏障,内存乱序的问题同样不需要考虑了。
  • 只有当使用无锁(lock-free)技术时,才需要考虑在合适的地方加入合适的memery barrier

Linux内存屏障使用注意事项:

  • 所有的 CPU Memory barrier(除了数据依赖barrier<smp_read_barrier_depends()>之外)都隐含了编译器barrier。
  • 这里的 SMP 开头的 Memory barrier 会根据配置在单处理器上直接使用编译器 barrier,而在 SMP 上才使用 CPU Memory barrier
  • CPU Memory barrier 中某些类型的 Memory barrier 需要成对使用

volatile 关键字与内存屏障

编译器在编译用 volatile 关键字修饰的变量的时候,对于该变量的访问操作,生成的指令会直接去该变量对应的内存中取值,而不会用寄存器暂存该变量的中间结果。

#define barrier() __asm__ __volatile__("": : :"memory")
#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)    #读写屏障
#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)   #读屏障
#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)    #写屏障

解决内核竟态的方法
https://blog.csdn.net/weixin_58458700/article/details/120497321

  • 中断屏蔽
    • 单核的cpu有效
    • 临界区很小,里面不可以有延时或者耗时的操作(copy_to_user)
    • 如果中断屏蔽的时间很长,会导致用户的数据丢失或内核的崩溃.
  • 自旋锁
    • 自旋锁是针对于多核处理器设计的
    • 自旋锁在上锁的时候会关闭抢占.
  • 信号量
    • 得不到锁的进程处于一个休眠的状态
    • 信号量不会关闭抢占
    • 保护的临界区可以很大
  • 互斥体
    • 保护的临界区可以很大,里面可以有延时,耗时,甚至休眠的操作
    • 在保护临界区较少的临界资源时,互斥体的效率高于信号量。
  • 原子变量/操作
    • 原子操作本身就是一个变量,这个变量的修改内核做了防竞态的过程。
    • 这个变量值修改的过程是通过内联汇编完成,对这个变量的操作看成一个不可被分割的整体。

Linux内核快速处理路径尽量多用slab而慎用kmalloc
https://blog.csdn.net/dog250/article/details/105544111

  • kmem_cache 是针对特定数据结构的独享内存池子,它以 最小化碎片 的原则为特定的场合提供 可高效访问 的内存,比如 sock,sk_buff 这些。
  • 当你调用 kmalloc(size, flags) 申请内存时,系统会根据你的size向上寻找一个最接近的kmem_cache,然后在其中为你分配所需的内存。
  • 并不是说 32 字节的结构体分配就一定会获得连续的内存,而 64 字节的就不会, 这完全取决于你的系统当前的整体 kmalloc 使用情况。
  • kmalloc 并不适合快速路径的内存分配,它只适合稳定的,离散的管理结构体的内存分配。
  • 大家之所以普遍喜欢用 kmalloc,因为它简单,快捷,少了 kmem_cache 的 create 和 destroy 的维护操作。
  • kmalloc 有个副作用,就是它只有固定的大小,比如你分配一个 24 字节大小的结构体,事实上系统会给你 32 字节。
  • 在诸如网络协议栈处理这种相对快速的路径中,比如skbuff,sock,nfconntrack 等结构体均是在自行维护的独享 kmem_cache 中被管理的,这保证了内存分配的尽可能的连续性,尽可能的最少碎片。
    • kmem_cache 的 obj 可以随意释放。
    • kmem_cache 的 obj 按照释放的逆序进行分配。
    • kmem_cache 的 free 相当于 push 操作,而 alloc 相当于 pop 操作。
  • 在连续的内存上进行遍历,其性能远超在离散的内存上进行遍历!
  • 我们使用自行维护的kmem_cache slab时,当从中分配的对象插入链表时,要尽量按照其内存地址的升序插入链表确定的位置,这样在遍历链表时可以达到最大化预取的效果。
    • 尽可能节省内存,保持内存的紧凑。
    • 提高 CPU dcache 的命中率,最大化 preload 效果。
  • 根据 slab 对象的内存使用 hlistaddbefore[rcu],hlistaddbebind[rcu]将对象插入 hlist 的特定位置,而不是简单使用 hlistaddhead。

ssh 隧道

ssh -CfNg -L 48175:127.0.0.1:48175 ubuntu@8.8.8.8

按进程关键字杀进程

ps -C "ssh -CfNg -L 48175:127.0.0.1:48175" -o pid= | xargs kill

https://blog.csdn.net/zqixiao_09/article/details/79265789
linux上的自旋锁有三种实现:

  1. 在单cpu,不可抢占内核中,自旋锁为空操作。
  2. 在单cpu,可抢占内核中,自旋锁实现为“禁止内核抢占”,并不实现“自旋”。
  3. 在多cpu,可抢占内核中,自旋锁实现为“禁止内核抢占” + “自旋”。

非抢占式内核: 如果一个进程在内核态运行,其只有在以下两种情况会被切换:

  • 其运行完成(返回用户空间)
  • 主动让出 cpu(即主动调用 schedule 或内核中的任务阻塞——这同样也会导致调用 schedule)

抢占式内核: 如果一个进程在内核态运行,其只有在以下四种情况会被切换:

  • 其运行完成(返回用户空间)
  • 主动让出 cpu(即主动调用 schedule 或内核中的任务阻塞——这同样也会导致调用 schedule)
  • 当从中断处理程序正在执行,且返回内核空间之前(此时可抢占标志premptcount须为0) 。
  • 当内核代码再一次具有可抢占性的时候,如解锁及使能软中断等。

其它

  • 禁止内核抢占只是关闭“可抢占标志”,而不是禁止进程切换。
    • 显式使用 schedule 或进程阻塞(此也会导致调用schedule)时,还是会发生进程调度的。
  • 对于多核抢占与多核非抢占的情况,在使用自旋锁时,其情况基本是一致的。
    • 因为在多核抢占的情况下,使用自旋锁会禁止内核抢占,这样多核抢占就相当于多核非抢占的情况。

被自旋锁保护的临界区代码执行时,它不能因为任何原因放弃处理器:

  • 被自旋锁保护的临界区代码执行时,不能进入休眠。
  • 被自旋锁保护的临界区代码执行时,不能被被其他中断中断。
  • 被自旋锁保护的临界区代码执行时,内核不能被抢占。

所以现代处理器在处理自旋锁时都会设定自旋上限时间以防死锁. 另自旋锁在单核非抢占式CPU上是无效的.被设为空操作,不做任何事.

C++性能优化(十二)——自旋锁
https://blog.csdn.net/A642960662/article/details/123029988

互斥锁

  • 属于 sleep-waiting 类型锁。Linux Kernel 2.6.x 稳定版开始,Linux 的互斥锁都是 futex (Fast Usermode Mutex)锁。
  • Futex 是一个在 Linux 上实现锁定和构建高级抽象锁如信号量和 POSIX 互斥的基本工具。
  • Futex 是由用户空间的一个对齐的整型变量和附在其上的内核空间等待队列构成。
  • 多进程或多线程绝大多数情况下对位于用户空间的futex的整型变量进行操作(汇编语言调用 CPU 提供的原子操作指令来增加或减少)
  • 而其它情况下则需要通过代价较大的系统调用来对位于内核空间的等待队列进行操作(如唤醒等待的进程/线程或将当前进程/线程放入等待队列)。
  • 除了多个线程同时竞争锁的少数情况外,基于futex的lock操作是不需要进行代价昂贵的系统调用操作的。
  • 互斥锁实际上是 count=1 情况下的 semaphore。

互斥锁缺点:

  • 等待互斥锁会消耗时间,等待延迟会损害系统的可伸缩性。
  • 优先级倒置。低优先级的线程可以获得互斥锁,因此会阻碍需要同一互斥锁的高优先级线程。
  • 锁护送(lock convoying)。如果持有互斥锁的线程分配的时间片结束,线程被取消调度,则等待同一互斥锁的其它线程需要等待更长时间。

自旋锁(spin lock)

  • 属于 busy-waiting 类型锁。
  • 在多处理器环境中,自旋锁最多只能被一个可执行线程持有。
  • 如果一个可执行线程试图获得一个被其它线程持有的自旋锁,那么线程就会一直进行忙等待,自旋(空转),等待自旋锁重新可用。
  • 如果自旋锁未被争用,请求锁的执行线程便立刻得到自旋锁,继续执行。
  • 自旋锁不会使线程状态发生切换,一直处于用户态,即线程一直都是 active 的;
  • 不会使线程进入阻塞状态,减少了不必要的上下文切换,执行速度快
  • 通常适用在时间极短的情况,因此操作系统的内核经常使用自旋锁。
  • 但如果长时间上锁,自旋锁会非常耗费性能。
  • 线程持有锁时间越长,则持有锁的线程被 OS调度程序中断的风险越大。
  • 如果发生中断情况,那么其它线程将保持旋转状态(反复尝试获取锁)。

互斥锁和自旋锁对比:

  • spinlock 不会使线程状态发生切换,mutex 在获取不到锁的时候会选择sleep。
  • spinlock 优点:没有耗时的系统调用,一直处于用户态,执行速度快。
  • spinlock缺点:一直占用 CPU,而且在执行过程中还会锁 bus 总线,锁总线时其它处理器不能使用总线。
  • mutex 获取锁分为两阶段
    • 第一阶段在用户态采用 spinlock 锁总线的方式获取一次锁,如果成功立即返回;
    • 否则进入第二阶段,调用系统的 futex 锁去 sleep,当锁可用后被唤醒,继续竞争锁。
  • mutex 优点:不会忙等,得不到锁会 sleep。
  • mutex 缺点:sleep 时会陷入到内核态,需要昂贵的系统调用。

几种自旋锁实现:

  • raw_spinlock:
    • 在单处理机环境中可以使用特定的原子级汇编指令 swap 和 test_and_set 实现进程互斥。
    • 多处理器环境目前多以锁总线形式保证 test_and_set 指令执行的原子性。
    • 由于传统自旋锁无序竞争的本质特点导致锁竞争争不公平。
      • 释放自旋锁时的重置操作将无效化所有其它正在忙等待的处理器的缓存。
      • 在处理器拓扑结构中临近自旋锁拥有者的处理器可能会更快地刷新缓存,因而增大获得自旋锁的机率。
    • 由于每个申请自旋锁的处理器均在全局变量 slock 上忙等待,系统总线将因为处理器间的缓存同步而导致繁重的流量。
  • ticket spinlock:
    • 排队自旋锁,线程将严格地按照申请顺序依次获取排队自旋锁,从而完全解决了不公平问题。
    • slock 字段被分成两部分 Owner 和 Next
      • 分别保存锁持有者和未来锁申请者的票据序号(Ticket Number)
      • 只有 Owner 和 Next 相等时,才表明锁处于未使用状态。
    • 在大规模多处理器系统和 NUMA 系统中
      • 由于执行线程均在同一个共享变量 slock 上自旋,申请和释放锁的时候必须对slock进行修改,将导致所有参与排队自旋锁操作的处理器的缓存变得无效。
      • 如果竞争比较激烈,频繁的缓存同步会导致繁重的系统总线和内存的流量,降低整体性能。
  • mcs spinlock:
    • 每个锁的申请者(处理器)只在一个本地变量上自旋。
    • 自旋锁的空间复杂度(即锁数据结构和锁操作所需的空间开销)为常数,占用空间大。
    • 在没有处理器缓存一致性协议保证的系统中也能很好地工作。
  • qspinlock:
    • 基于 mcs spinlock 设计思想但解决了接口不一致或空间太大的问题

在CPU较少的情况下, qspinlock的性能和ticket spinlock的性能差不多, 在CPU较多的情况下,qspinlock的性能远好于ticket spinlock。

Linux 性能优化
https://blog.csdn.net/a642960662/category_11641226.html

  • stress 压力测试工具
  • sysbench 压力测试工具
  • sysstat 性能监控工具
  • BCC 性能监控工具
  • 性能监控工具
  • 网络配置工具
  • 网络流量监控工具
  • 网络测试工具
  • Kernel Bypass
  • CPU 性能分析工具
  • CPU 性能优化原理
  • CPU 性能调优
  • CPU Cache
  • CPU 绑定
  • 中断绑定

从自旋锁、睡眠锁、读写锁到 Linux RCU 机制讲解
https://blog.csdn.net/u010180372/article/details/119470638

单核

  • 我们只需要通过关中断 就可以实现 sequential access
  • local_irq_disable() 和 preempt_disable() 就能实现

多核

  • 对于一个数据结构, 一旦他已经被一个 core 给 lock 了,当前运行在另一个 core 上的 thread 就需要等待锁释放, 所以需要一个循环等待的过程, 叫做自旋.
  • 具体实现的关键部分是通过 CPU 提供的一种 swap (test_and_set)指令,执行一个原子操作的读出值和放入新值。
    • 把 1 放进去, 拿出来 1, 说明被锁了
    • 把 1 放进去,拿出来 0,说明当前 thread/core 拿到这个锁

rics-v 代码

void acquire(struct spinlock *lk)
{
    push_off(); // disable interrupts to avoid deadlock.
    if(holding(lk)) panic("acquire");

    // On RISC-V, sync_lock_test_and_set turns into an atomic swap:
    //   a5 = 1
    //   s1 = &lk->locked
    //   amoswap.w.aq a5, a5, (s1)
    while(__sync_lock_test_and_set(&lk->locked, 1) != 0)
        ;

    // Tell the C compiler and the processor to not move loads or stores
    // past this point, to ensure that the critical section's memory
    // references happen strictly after the lock is acquired.
    // On RISC-V, this emits a fence instruction.
    __sync_synchronize();

    // Record info about lock acquisition for holding() and debugging.
    lk->cpu = mycpu();
}

内存屏障做的事情

  • 在编译器上很好理解就算防止编译过程的指令重排导致的持有锁状态更新和锁实际状态的不一致,
  • 而其在 CPU 上其实就是做一个简单的清空流水线,

spinlock 的 overhead

  • 内存屏障导致的清空流水线浪费一个流水线长度,
  • 循环等待的不断 CAS 的过程
  • amoswap 涉及多核 CPU 的 cache coherence MESI 的东西.

性能保证

  • 关抢占, 关中断后能够使需要锁的操作快速运行完,防止拿到锁后 context switch 出去导致别的线程/核心需要等该核心轮转
  • Linux spinlock 的实现:spinlock 持有 lock 之后关了 preempt 不关 interrupt。
  • 有一个 irqsave 版本会关,要点是:process 和 中断都想获取一个资源的时候,就要 avoid deadlock。

仔细看了下这个排队自旋锁ticket spinlock,解决锁竞争不公平的的实现太巧妙了,就用 Owner 和 Next 俩个半拉(用的一个union)的字段就完美解决了。

还了解了下用户态的自旋锁和内核态的自旋锁不是一回事,因为用户态的自旋锁不能关中断,也不能关抢占,所以不能防止进程被切走,所以临界区性能是无法得到高性能保障的,所以应用层的自旋锁要有一些特殊的优化,比如用 PAUSE 指令让 CPU 执行一些 NOP 类似的效果,避免 reorder 和频繁地清空流水线,再比如说在单核 CPU上提前 yield 防止忙等待,降低CPU的功耗和发热。

频繁的 CAS 操作会产生大量 hazard 的 load 和 store,让流水线指令重排机制认为出现 memory order violation,有可能为了安全而清空流水线,pause 能避免大量循环后再 context switch。

虚拟机 ESXi、PVE、unRaid对比
https://zhuanlan.zhihu.com/p/166352130

  • ESXi,是 VMWare vSphere Hypervisor 套件之下重要组件。前身是 ESX,依赖 Linux 源码,后来抛弃 Linux 源码做成了 ESXi。
    • 整个产品商用气息浓重,界面清晰易用,但硬件兼容性较差(主要面向服务器),没什么扩展性(毕竟不是 linux)。
  • PVE,全称 Proxmox Virtual Environment,是基于 Debian 的 Linux 系统,虚拟机内核为 KVM。
    • 硬件兼容性优秀。界面功能不强,很多操作要靠命令行,但扩展能力几乎是无限的。
  • unRaid,其实是个NAS系统,是基于Slackware的Linux系统,虚拟机内核也是KVM。
    • 磁盘阵列管理非常有特色,灵活性很高。同时还有很不错的插件、Docker和虚拟机支持。

mysql

中位数

https://stackoverflow.com/questions/1291152/simple-way-to-calculate-median-with-mysql

SELECT AVG(dd.val) as median_val
FROM (
SELECT d.val, @rownum:=@rownum+1 as `row_number`, @total_rows:=@rownum
  FROM data d, (SELECT @rownum:=0) r
  WHERE d.val is NOT NULL
  -- put some where clause here
  ORDER BY d.val
) as dd
WHERE dd.row_number IN ( FLOOR((@total_rows+1)/2), FLOOR((@total_rows+2)/2) );

两个数据库之间导数据
How can I transfer data between 2 MySQL databases?
https://stackoverflow.com/questions/3242504/how-can-i-transfer-data-between-2-mysql-databases

We have also used FIFO’s to great effect to avoid the overhead of actually writing to disk,
or if we do need to write to disk for some reason, to pipe it through gzip.

mkfifo /tmp/myfifo
gzip -c /tmp/myfifo > /tmp/mytable.csv.gz &
SELECT * FROM mytable INTO OUTFILE '/tmp/myfifo'
  FIELDS TERMINATED BY ',' 
  OPTIONALLY ENCLOSED BY '"' 
  ESCAPED BY '\\\\' 
  LINES TERMINATED BY '\\n' ;

gunzip -c /tmp/mytable.csv.gz > /tmp/myfifo &
LOAD DATA INFILE '/tmp/myfifo' INTO TABLE mytable 
  FIELDS TERMINATED BY ',' 
  OPTIONALLY ENCLOSED BY '"' 
  ESCAPED BY '\\\\' 
  LINES TERMINATED BY '\\n' ;

How to take mysql dump of selected columns of a table
https://stackoverflow.com/questions/15264597/how-to-take-mysql-dump-of-selected-columns-of-a-table

mysql> CREATE TABLE `tempTable` AS SELECT `columnYouWant` from `table`;
$> mysqldump yourDB tempTable > temp.sql

$> mysql yourDB < temp.sql
mysql> RENAME TABLE `table` TO `tableBackup`, `tempTable` TO `table`;

查看每个表的大小

SELECT
  TABLE_NAME AS `Table`,
  ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024) AS `Size (MB)`
FROM
  information_schema.TABLES
WHERE
  TABLE_SCHEMA = "dirtable"
ORDER BY
  (DATA_LENGTH + INDEX_LENGTH)
DESC
limit 15;

流媒体

SRS是一个简单高效的实时视频服务器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT/GB28181。
https://ossrs.net/lts/zh-cn/docs/v4/doc/introduction

开源复刻:OBS如何支持直播多人连麦,可连麦的在线发布会
https://github.com/ossrs/srs/issues/2749

GO

Go语言中你不知道的Interface详解
https://www.jb51.net/article/135149.htm

传统接口的缺陷

  • 侵入式通过 implements 把实现类与具体接口绑定起来了,因此有了强耦合;
  • 如果我修改了接口,比如改了接口方法,则实现类必须改动;
  • 如果我希望实现类再实现一个接口,实现类也必须进行改动;
  • 后续跟进者,必须了解相关的接口。

GO 接口的优点

  • 只要实现了与接口定义相同的方法,就算实现了某个接口,最重要的,随着代码的增加,你的类结构不会像 Java 那样发生爆炸。
  • 实现类的时候也不需要像 Java、PHP 一样引入各种接口,有可能你定义类的时候,某个接口还不存在。

elasticsearch

elasticsearch性能优化(一)
https://www.cnblogs.com/jelly12345/p/15322814.html

TF/IDF vs BM2.5
https://zhuanlan.zhihu.com/p/573284091
https://blog.csdn.net/qq_40859560/article/details/109147840

TF/IDF

  • 直觉上,一个词项在文档中出现次数越多,那么该词项和文档的相关性也应该越大。
  • 文档频率越大的词,在文档中越常见,区分作用越小,那么权重也应当越小。
  • 优点:
    • 简单,快速,如果语料库是不变的话,可以提前离线计算好语料库中所有词的 tfidf 值
  • 缺点:
    • 仅以“词频”度量词的重要性,后续构成文档的特征值序列,词之间各自独立,无法反映序列信息
    • tfidf 得到是一个稀疏而庞大的矩阵,需要采用降维方式,才方便做后续的文本任务
      • 而降维可能会损失一些信息,同时降维的也会提高模型的复杂度,而失去了原本快速的优点
    • tfidf 得到的 embedings 再输入后续的模型,做文本分类、文本匹配等任务,在效果上通常会差于采用词向量模型训练得到的 embedding。

BM25

  • BM25与之不同,它在TF计算方法中增加了一个常量k,用来限制TF值的增长极限。
  • 业务上可以理解为某一个因素的影响强度不能是无限的,而是有个最大值,这也符合我们对文本相关性逻辑的理解。
  • bm25 其实就是把 query 中每个词,在每篇文档中的 tfidf(改良后的)值求和即为该query与该文档的相似性得分。
  • 优点
    • 可以方便线下做离线先计算好文档中出现的每一个词的 idf 并保存为一个字典
      • 当用户搜了一个 query,直接分词然后查字典就能得到这个词的 idf,如果字典中没有idf值无意义,因为R=0。同于tfidf。