202306

linux

ModSecurity3_Nginx 指南
https://www.jianshu.com/p/d22f3914d153

理财

加仓方法

https://mp.weixin.qq.com/s/vBI_JG20xEDiWaqKVc8NXw

  • 定投加仓法:
    • 每个月设定一个或者多个定投日,只在定投日买入基金固定的金额。
    • 适合于那些没有过多时间精力投入到研究市场估值、宏观经济状况等因素的投资者。
  • 指数加仓法:
    • 根据单日指数的跌幅来决定是否加仓的。
    • 这最好是有纪律性的,而不是凭感觉。
      • 比如当单日跌幅大于某个数值,就可以加仓;
      • 或者近几日跌幅大于某个数值,就加仓。
    • 沪深 300 指数近 20 年单日跌幅超过一定比例的次数和概率
      • 单日跌幅超过 1% 的有 954 次,发生的概率是 20%;
      • 单日跌幅超 2% 的有 368 次,发生概率是 8%。
      • 具体按多少加仓,就看你想触发的加仓概率是多少。
    • 为了防止市场跌跌不休,指数的跌幅一直超过设定的参数,还需要加一个参数,
      • 即“ n 个交易日不重复触发”,通常可以选择 3、5、10 个交易日。
  • 正金字塔加仓法:
    • 简单地说,就是跌的越多,买的也越多。
    • 例如,投资者可以把资金分为6份,
      • 当下跌达10%时,加仓一份,也就是1/6。
      • 当下跌达20%时,加仓两份,也就是2/6。
      • 当下跌达30%时,加仓三份,也就是3/6。
      • 当然了,在按批次加过仓后,如果你还有充足的资金,可以继续加仓,
        一直到你觉得市场不在被低估为止,结束加仓。
    • 这种加仓的方法需要在开始投资之前,就确立好准备投入的总资金额,以便于将资金分配。
    • 到底跌多少再加仓,最好结合基金的回撤,这就引申到了下一个加仓方法。
  • 回撤加仓法:
    • 根据基金的回撤来买入。可以是等额买入,也可以是正金字塔买入。
    • 第一种,把 1 万元分成三等份,每跌 10%,补一份,就属于等额买入。
    • 第二种,把 1 万元分成三份,注意不是三等份,
      • 第一份占资金的 1/6,第二份占资金的 2/6,第三份占资金的 3/6,
      • 这就属于正金字塔买入,拉低成本价的效果更加明显。
    • 如果基金没跌这么多呢,比如跌了20%,万一只补仓了一点怎么办?
      • 假设跌 14%,补仓 = 10000*14%/42%=3333.33 元;
      • 然后跌到 20% 的时候,还可以补仓,补仓金额 = 10000*20%/42% - 第一次补仓的金额
        = 4761.90-3333.33=1428.57 元。
      • 如果跌到 25%,还可以继续补。
  • 对比:
    • 定投加仓法
      • 优势: 简单易操作、适合小白和繁忙上班族、资金支出稳定
      • 劣势:缺少对于市场估值的判断、跌幅较大的时候买的少
    • 正金字塔式加仓法
      • 优势:更低的持仓成本、总资金量确定、 可以与回撤加仓法搭配使用
      • 劣势:小回撒导致加仓不足
    • 回撤加仓法
      • 优势:资金投入灵活、参照历史最大回撒跌也不慌
      • 劣势:极端行情导致回撒超出、需较多精力跟踪回撒,小回撒导致加仓不足
    • 指数加仓法
      • 优势:直观易懂,明确下跌带来的机遇
      • 劣势:特定基金与指数相关性低,资金量不确定,跌幅闭值设罟难度大

雷公

趋势交易流程:

  1. 当前趋势的方向是怎样的?
  2. 趋势的斜率(时钟方向)是怎样的?
  3. 你打算交易的方向是怎样的?
  4. 你的预期是怎样的?
  5. 满足怎样的条件止盈出局?
  6. 你的底线是什么?
  7. 满足怎样的条件止损出局?
  8. 根据5、7两项计算理论盈亏比。
  9. 这笔交易你能承受的最大亏损金额是多少?
  10. 根据9.来确定持有头寸数量。

我的持仓构成:

  • 首先,大盘指数是机会成本,这部分投资占比30%以上;
  • 其次,个股投资主要分为两类:
    • 1)垄断巨头企业(长期持有)和
    • 2)动量交易(短期投机)。
    • 个股投资部分占比不超过30%;
  • 此外,我还持有30%左右的固定收益类品种,以此获取日常现金流。
  • 最后,10% 左右的备用金,以防不测。

日常现金流

  • 作为职业投资者,我的日常现金流主要就是来自固定收益类品种。
  • 持有债券还是持有高息存款,取决于两者的现金分红率的高低。
  • 目前我主要持有 GIC,平均利率在 4.5% 左右。
  • 最后,10% 备用金主要用于在市场不好的时候作对冲。

趋势的五种类型与交易策略

  • 第一类:1点钟~12点钟方向,斜率加速上涨的趋势。
    • 这类属于斜率加速的行情,通常出现在趋势刚开始的阶段,或者是趋势即将结束的阶段。
    • 交易策略:
        1. 无持仓,不参与;
        1. 有持仓,不急于兑现。
        1. 关注市场转向的迹象,等待明确出现关键性波动之后再考虑兑现出局。
  • 第二类:2点半~1点钟方向,稳定的上涨趋势。
    • 这类趋势的斜率稳定,可以走很长时间,是大行情的摇篮。
    • 交易策略:
        1. 趋势形成过程中,第一次回撤到短期均线、中期均线、长期均线,都是非常好的进入位置;
        1. 回撤有可能击穿均线,但不应改变均线运行方向;
        1. 进入时机:底部构造+低一级别多头排列
  • 第三类:2点半~3点半方向,横向整理姿态的趋势。
    • 这种类型的趋势也称之为「密集成交区」,通常是大周期趋势的中途休息站。
      休整结束之后,通常会延续原有大周期趋势的方向。
    • 交易策略:
        1. 横向波动的时间要足够长、均线密集之后;
        1. 在突破密集成交区之前完成了均线多头排列,可进入,赌突破。
  • 第四类:3点半~5点钟方向,稳定的下跌趋势。
    • 这类趋势的方向与第二类相反,交易策略相同但方向相反。
      第五类:5点钟~6点钟方向,加速下跌的趋势。
    • 这类趋势的方向与第一类相反,交易策略相同但方向相反。

操作个股是否需要以大盘指数为参考?

  • 不需要。
  • 我的每一只股票都会有各自的止损或止盈位置的设定,这些设定并不依据大盘指数为参考。
  • 很多时候,大盘还处在弱势格局,但是有一些股票已经满足交易条件,我就会进入交易,不理会大盘。
  • 同理,很多时候,大盘尚处在强势,而我的股票却已经纷纷触发止盈止损出局,我同样也不会理会大盘。
  • 在大盘很弱的时候,满足进入条件的股票却越来越多,这说们市场即将走强。
  • 相反,当满足退出条件的股票越来越多,而大盘还处在强势,这种强势大概率是虚假的。

雷公的 TradingView指标

掌握这些概念,我想你会想明白很多事情

  • 美元 是全球的资本成本,
  • 美债 是美元的资本成本,
  • Bitcoin 反应投机资本的活跃度。

杂项

  • 为了反对而反对,这是初学交易者最容易犯的错误。
  • 优秀的交易者在头脑中同时存在正反两方面的意见,不断地自我博弈过程,动态调整方向。
  • 你不必反驳任何人的观点,没有人掌握真理,多数人只是在表达情绪。
  • 请记住,你最大的对手,就是你自己——不要让情绪降低了智商。

杂项

  • 在我的词典中是没有「主力」「大户」这类假想敌的。
  • 我每次亏损并不是有人故意陷害所致,事实上,往往是我没有计划的随机交易、或者有计划却未能坚决执行时对我的伤害最大。
  • 交易者最大的对手不是别人,就是你自己。

杂项

  • 交易,不是一场「猜涨跌」的游戏。
  • 交易,是一门生意。你需要知道怎样更容易赚到钱;
  • 你需要拥有一个在你睡觉时也能为你赚钱的系统;
  • 你需要界定你的退出机制。

风险量化:

  • 交易资金管理的核心是风险数量化。 我的每一笔交易都设有止损价格。
  • 依据止损价格来明确每一笔交易的最大损失金额,由此倒算出我应该持有的头寸数量,这就是风险量化。
  • 每一笔交易都有对应的风险值,整个 Portfolio 的风险就可以数量化。
  • 这样就很清楚在极端情况下总体风险有多大。
  • 最重要的是,可以根据总体风险值来设计对冲策略。

亏钱原因:

  • 不懂看图,是绝大多数人在金融市场亏钱的主要原因;
  • 把图画得太复杂,是绝大多数会看图的人亏损的主要原因;
  • 试图找到一个决胜指标或者某个神奇数字,又是多数人在建立交易系统过程中亏钱的主要原因。
  • 在金融市场里长期获利,我认为以下两个认知非常重要。所有的方法工具都必须围绕这两点展开:
      1. 识别趋势。什么时候市场运动的方向对我有利,什么时候不利。不利的时候,不要参与或者出局;
      1. 趋势对我有利的时候,要抱住不放。直到趋势开始对我不利。 简而言之:认清趋势,让时间成为朋友。

币圈的繁荣,

  • 1)是建立在全球流动性泛滥基础上的,
  • 2)是传统投资领域(股市债市房地产)资本外溢的结果,
  • 3)在高速发展过程中的制度性漏洞被充裕的流动性掩盖。

做投资两件事最重要:

  • 第一,你必须要知道风险在哪,风险必须可以数量化;
  • 第二,你也必须要有办法对冲风险。有办法对冲的风险就不是风险,暂时没办法对冲的风险就不要去碰。
  • 本质上说,投资是在解决一系列风险问题的同时并获取回报的过程。
  • 风险越大、不确定性越大,你最终获取的回报也就越大。

英语

听力练习
https://www.youzack.com/ListeningExercise/Episode/3668/?mediaType=audio

腾讯微云网盘:
https://share.weiyun.com/ChATk7JK
请安装微云网盘客户端APP后,用客户端下载

百度网盘:
https://pan.baidu.com/s/14ryQc0HVxSpzCGi9scQLaA
提取码:2021
请安装百度网盘客户端APP后,用客户端下载

听力课堂
https://www.tingclass.net/show-5026-9-1.html

前端

傻傻分不清楚

  • Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。
  • NuxtJS 让你构建你的下一个 Vue.js 应用程序变得更有信心。这是一个 开源 的框架,让 web 开发变得简单而强大。
  • Next.js 为您提供生产环境所需的所有功能以及最佳的开发体验:包括静态及服务器端融合渲染、 支持 TypeScript、智能化打包、 路由预取等功能 无需任何配置。

多语言、登录SSO、日志、健康检查全都有 https://github.com/andrechristikan/ack-nestjs-boilerplate

JS原生—歌词滚动效果案例
https://blog.csdn.net/llllllllolllllll/article/details/129340505

font-size的改变就导致了元素几何信息的变化,几何信息的变化就意味着会导致reflow,会使页面重新布局,影响效率。 而transform 变形,并不是在渲染主线程中执行,不占用主线程,而是在合成线程中执行,最终的实现也是交给cpu,所以不会导致页面重新布局,不影响效率。

Vue3中使用this
https://juejin.cn/post/7028386809939755021

const { proxy, ctx } = getCurrentInstance()

Vue3中如何使用WeUI
https://blog.csdn.net/wangyangnuli/article/details/121397759

npm install weui.js weui -S

import { createApp } from 'vue'
import store from '@/store'
import weui from 'weui.js'
import 'weui'
import App from '@/App.vue'
import router from '@/router'
const app = createApp(App)
app.config.globalProperties.$weui = weui
app.use(store).use(router).mount('#app')


import { ref,getCurrentInstance } from 'vue'
const $weui = proxy.$weui;

const test = () => {
  $weui.alert("服务器错误");
}

WeUI.JS 中文文档
https://www.kancloud.cn/ywfwj2008/weuijs

十分钟,带你了解 Vue3 的新写法
https://juejin.cn/post/7225267685763907621

weui 文档
https://weui.shanliwawa.top/weui/index.html
https://weui.io/

vue3
https://www.runoob.com/vue3/vue3-v-for.html

助你上手Vue3全家桶之Vue-Router4教程
https://blog.csdn.net/pdd11997110103/article/details/121036684

游戏

模拟器游戏下载
https://www.emulatorgames.net/

浏览器中的 n64 模拟器
https://www.neilb.net/n64wasm/

mysql

自从MySQL启动起来的QPS的平均值

Threads: 350  Questions: 112619252828  Slow queries: 1156228  Opens: 138939  Flush tables: 1  Open tables: 2048  Queries per second avg: 23283.127

if (!(uptime= (ulong) (thd->start_time.tv_sec - server_start_time)))
    queries_per_second1000= 0;
else
    queries_per_second1000= thd->query_id * 1000LL / uptime;

length = my_snprintf(buff, buff_len - 1,
                    "Uptime: %lu  Threads: %d  Questions: %lu  "
                    "Slow queries: %llu  Opens: %llu  Flush tables: %lu  "
                    "Open tables: %u  Queries per second avg: %u.%03u",
                    uptime,
                    (int) thd_manager->get_thd_count(), (ulong) thd->query_id,
                    current_global_status_var.long_query_count,
                    current_global_status_var.opened_tables,
                    refresh_version,
                    table_cache_manager.cached_tables(),
                    (uint) (queries_per_second1000 / 1000),
                    (uint) (queries_per_second1000 % 1000));

other

制作ascii图表
https://asciiflow.com/#/

rust

https://rust-on-nails.com
Rust全栈WEB开发指南,体系化介绍了作者认为rust WEB开发过程中比较好的一些工具,也包含CI/CD、数据库等,有点意思

english

As the labeled abuse data is limited and more unsupervised approaches are explored, the feature quality becomes the key for machine learning models to succeed. The features used by models normally belong within two categories: 1) value features and 2) counting features. Value features are the most common category; they directly use the value of raw features, such as IP address, name, email, etc. Some abuse patterns can be found by finding identical or similar feature values among massive requests/users (e.g., clustering); some abuse patterns can be found by identifying different feature values from the same entity (e.g., account takeover). Counting features are based on the feature counting numbers within a certain time period, which are commonly used for large-scale abuse prevention. Various machine learning approaches (supervised/unsupervised) basically try to find the complex relationship between these features.

Counting features are based on the feature counting numbers within a certain time period, which are commonly used for large-scale abuse prevention. Various machine learning approaches (supervised/unsupervised) basically try to find the complex relationship between these features.

When abusers start to change their signals once anti-abuse defenses are applied, we often see both value features and counting features are subject to be compromised.

Rules and models based on value features often need to adjust parameters or retrain if feature values are changed/spoofed.

Counting features will lose the visibility to differentiate bot and human traffic once abusers lower their request rate.

The fact that features are constantly altered or changed can significantly degrade the performance of rules and models.

If you compare yourself to others in tech, you are going to rob yourself of your happiness faster than Nicolas Cage steals the Declaration of Independence.

One of the biggest benefits of the tech industry is being able to collaborate with extremely talented people - Don’t turn that into downside.

There are always going to be brilliant peers who grow at a much faster rate. That’s what we all signed up for when we decided to work in this crazy field.

You are only hurting yourself when you treat others’ accomplishments as a baseline for yourself, creating an unrealistic growth deadline to hit.

Your career is a marathon not a race. In order to keep on running, you can’t hold yourself back feeling bad that you aren’t at the same level as someone else.

For those ahead of you, extract the learnings from their success, apply it to your own work, and keep on chugging along. You will eventually get to where you want to go.

To learn more about maintaining a healthy mentality, not comparing yourself to others, and long-term career growth, check out the in-depth discussion here:

As models are only able to learn from the information captured by the features, any information missed by the features will be overlooked by the models as well.

Higher quality features to capture more insights and provide higher resistance to attack variability are essential for successful anti-abuse defense.

There are other technologies that could serve the purpose, but they often require collecting additional user information.

算法

畅销20年,被麻省理工推荐,每个程序员都该读的编程珠玑
https://mp.weixin.qq.com/s?__biz=MzA3NTIzMzIxNQ==&mid=2652879187&idx=1&sn=4caaf94034ca7ff1313bc1d7b012dbfd&chksm=8498bb83b3ef3295785aca3b8aeba035e72bf7b2da2cda53fd0c5e1d7e333a0122292ab753b5&scene=27

《编程珠玑》习题练习In Python——第三章 数据决定程序结构
https://blog.csdn.net/vincent_hbl/article/details/53446014

《编程珠玑》习题练习In Python——第二章 啊哈!算法
https://blog.csdn.net/vincent_hbl/article/details/53438282

Programming Pearls Second Edition
https://github.com/Folgerjun/Programming-Pearls

202305

linux

sed

在每行的头添加字符,比如"HEAD",命令如下:

sed 's/^/HEAD&/g' test.file

#在每行的行尾添加字符,比如“TAIL”,命令如下:
sed ‘s/$/&TAIL/g’ test.file

Linux NFS服务的权限设置和身份映射
https://blog.csdn.net/m0_46756244/article/details/105342440

  • 权限主要分两种,ro(默认,只读)rw(读写)sync(同步,必须加);客户端还可以用*来表示,就代表所有客户端都可以访问
  • 在设置权限后,还应别忘了系统层面的权限设置
  • NFS 服务不具备用户身份验证的功能,而是基于客户端的 IP 来进行认证的
  • 在服务器上会有这么一个 nfsnobody 匿名用户,然后客户端在用nfs服务访问服务器上的共享目录时,就会被映射成这个用户来访问
  • 用户映射
    • root_squash,当 NFS 客户端以 root 用户身份访问时,映射为 NFS 服务器的 nfsnobody 用户
    • no_root_squash,当 NFS 客户端以 root 身份访问时,映射为 NFS 服务器的 root 用户,一般不建议采用。
    • all_squash,无论 NFS 客户端以哪种用户身份访问,均映射为 NFS 服务器的 nfsnobody 用户。
  • 如果在服务器端赋予某个用户对共享目录具有相应权限,而且在客户端正好也有一个相同 UID 的用户,那么当在客户端以该用户身份访问共享时,就会被映射成具有相同 UID 的用户,比如服务端和客户端都是 ubuntu 默认用户,避免这种情况就用 all_squash

linux 命令行查词
https://www.cnblogs.com/fusheng-rextimmy/p/15371057.html

sudo apt-get install ruby
sudo gem install fy
fy love

NGINX caching proxy fails with SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
https://stackoverflow.com/questions/25329941/nginx-caching-proxy-fails-with-ssl23-get-server-hellosslv3-alert-handshake-fail

proxy_ssl_server_name on;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

nginx upstream failover 容错机制
https://blog.csdn.net/bigtree_3721/article/details/72792141

  • 失效节点的 6 种状态
    • time out
    • connect refuse
    • 500、502、503、504
    • 后四项 5XX 需要配置 proxy_next_upstream 中的状态才可以生效
  • 负载均衡方式一共有 5 种
    • rr(轮询模式)
    • ip_hash
    • fair
    • url_hash
    • weight(加权)。

编程

HyperLogLog 使用及其算法原理详细讲解
https://blog.csdn.net/qq_41125219/article/details/119776824

Dotnet Async Guidance
https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/master/AsyncGuidance.md

Tailwind CSS:百万美元启示录
https://hardcored.substack.com/p/tailwind-css

rust

安装 rust
https://www.rust-lang.org/tools/install

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

Rustup - Rust工具链安装器
https://zhuanlan.zhihu.com/p/382810160

rust 教程
https://doc.rust-lang.org/rust-by-example/hello/print.html

通过例子学 Rust
https://rustwiki.org/zh-CN/rust-by-example/

Rust 程序设计语言
https://rustwiki.org/zh-CN/book/

vimrc 设置 F5 编译运行

autocmd FileType rust nnoremap <buffer> <F5> :!rustc % -o a.out && ./a.out<CR>

英语

175个最实用的英语会话句型
https://www.cnblogs.com/winrarz/p/16885550.html

python

python协程(1): 基本介绍及yield实现协程
https://blog.csdn.net/qq_37674086/article/details/113243190

vim

光标移动

  • gg 到文档第一行
  • G 到文档最后一行
  • 0 到行首(第 1 列)
  • ^ 到第一个非空白字符
  • $ 到行尾
  • Ctrl-B 和 Ctrl-F 以及 PageUp 和 PageDown 按全页滚动
  • Ctrl-U 和 Ctrl-D 默认滚动半页
  • Ctrl-Y 和 Ctrl-E 滚动一行
  • zz 把当前行置为屏幕的中央
  • zt 把当前行置于屏幕的顶端
  • zb 把当前行置于屏幕的底端
  • H 移动到屏幕顶端
  • M 移动到屏幕中间
  • L 移动到屏幕底部
  • w or W 向右移动到下一单词开头
  • e or E 向右移动到单词结尾
  • b or B 向左移动到单词开头
  • % 跳转到相配对的括号
  • gD 跳转到局部变量的定义处
  • { 跳到上一段的开头
  • } 跳到下一段的的开头
  • ( 移到这个句子的开头
  • ) 移到下一个句子的开头
  • [[ 跳转至上一个函数(要求代码块中’{‘必须单独占一行)
  • ]] 跳转至下一个函数(要求代码块中’{'必须单独占一行)

php

tinker 的输出默认不翻页
https://github.com/bobthecow/psysh/wiki/Config-options

php -d cli.pager=cat artisan tinker

202304

python

SQLite Vacuum
https://www.runoob.com/sqlite/sqlite-vacuum.html

VACUUM 命令通过复制主数据库中的内容到一个临时数据库文件,然后清空主数据库,并从副本中重新载入原始的数据库文件。这消除了空闲页,把表中的数据排列为连续的,另外会清理数据库文件结构。

基于selenium、BeautifulSoup与goose3的动态网络爬虫(以东方视野为例)
https://blog.csdn.net/qq_36274515/article/details/89631676

Flask-单元测试
https://blog.csdn.net/HuangXiongjin/article/details/103560721

Celery Daemonization
https://docs.celeryq.dev/en/latest/userguide/daemonizing.html#daemon-systemd-generic

python究竟要不要使用多线程

  • GIL 的特性,也就导致了 python 不能充分利用多核 cpu。
  • 而对面向 I/O 的(会调用内建操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。
  • 如果线程并未使用很多 I/O 操作,它会在自己的时间片一直占用处理器和 GIL。

创业

80+盈利创始人推荐,25本最佳书籍盘点!
http://www.yitb.com/article-38436

重新理解创业里程碑
https://yitanger.feishu.cn/docx/WQuRdqYE4oos1txDxvZcJkf2nL7

重磅案例课:小龙虾外卖
https://yitanger.feishu.cn/docs/doccnV1Yg9Jr1suZLQGspt6UfMe#DA9tR6

壁垒必修:预判项目长期壁垒课程
https://yitanger.feishu.cn/docs/doccnettFMyMZ8BuawbJBa8lUng#NwIJ9k

落地之夜,案例分享
https://yitanger.feishu.cn/docx/WLrBdameeokuKdxU6VgcHLpknpf

创业书单
https://yitanger.feishu.cn/docx/VBPEdcCl0oGlIwxTtu8cDwL8nle

ai

https://civitai.com/images/370200?modelId=4823&postId=108729&id=4823&slug=deliberate
https://civitai.com/images/213712?modelId=4823&postId=111233&id=4823&slug=deliberate
https://civitai.com/images/313863?modelId=4823&postId=116835&id=4823&slug=deliberate
https://civitai.com/images/392042?modelId=28620&postId=83099&id=28620&slug=mixreal-v2-sd-21

投资

8分钟教你什么是量比!
https://zhuanlan.zhihu.com/p/394928988

量比定义

  • 成交量是股价技术分析的重要指标,而分析成交量最重要的工具之一就是量比,量比是衡量相对成交量的指标
  • 它是指股市开市后平均每分钟的交易量与过去五个交易日平均每分钟的交易量之比。
  • 量比的数值越大,说明该股市场很活跃。
  • 量比的数值越小,说明该股市场很冷清。
  • 同时通过分析量比指标也能了解主力短期动向,适用于短线,量比选股法就是用于短期。

量比使用

  1. 当量比大于1时,说明当日每分钟的平均交易量大于过去五日平均每分钟交易量,交易比较活跃,为放量。
    • 当量比小于1时,说明交易比较清淡,为缩量。
  2. 当量比在 0.5 倍以下时,说明交易清淡,呈缩量情形,没有较大的分析意义。
  3. 当量比在 0.5-1.5 倍区间时,说明成交量为正常水平,需要观察,等待进场时机。
  4. 当量比在 1.5-2.5 倍区间时,说明成交量放量比较温和,应结合价格分析,
    • 如果股价也呈温和上涨态势,则可继续持有;
    • 如果股价呈下跌态势,那么该趋势短期内可能继续延续下去,应考虑止损离场。
  5. 当量价在 2.5-5 倍区间时,说明成交量放量较明显,
    • 如果股价在支撑位或压力位附近时,说明价格大概率会突破该关键位置,可以相应地采取行动。
  6. 当量比在 5-10 倍区间时,说明成交量放量较剧烈,
    • 如果股价在低位出现这种情况说明股价后期上涨的动力大;
    • 如果股价在高位并且股价已经拉升过了,应小心,可能为Z力的诱多行为,为出货做准备。
  7. 当量比在 10 倍以上的区间,说明成交量放巨量,为异动,物极必反,一般进行反向操作,
    • 如果股价在上涨趋势中,说明股价大概率见顶,可能后期会下跌,
    • 如果股价在下跌趋势的末期,则后期股价可能会大概率上涨。
  8. 当量比在 20 倍以上的区间,说明此时为极端放量,具有很强的反转信号,
    • 如果股价在高位滞涨,说明股价后期会下跌,应立刻离场。
    • 如果股价在下跌的趋势中,说明股价即将见底,可以进场等待拉升。

java

Spring Security Oauth2之获取token流程分析
https://blog.csdn.net/ityw520/article/details/128079499

oauth2的token认证接口/oauth/token、/oauth/check_token、/oauth/authorize在哪个包里
https://blog.csdn.net/qq_33036061/article/details/107076918

Non-resolvable parent POM 解决。分析 maven parent 解析顺序。
https://blog.csdn.net/wangrui1605/article/details/113746438
maven–解决was cached in the local repository, resolution will not be reattempted until the update
https://blog.csdn.net/feiying0canglang/article/details/125673756

Maven的常用命令
https://zhuanlan.zhihu.com/p/411883656

关于maven多module的依赖问题
https://www.cnblogs.com/westlin/p/10908778.html

Maven的聚合(多模块)和Parent继承
https://www.jb51.net/article/153441.htm

other

微服务经典文章:微服务 | Martin Fowler
https://zhuanlan.zhihu.com/p/472964950

AWS 上的数据加密策略
http://blog.light2cloud.com/?p=94

「 通达信 」的基本使用及常用设置
https://zhuanlan.zhihu.com/p/545826458

Nginx proxy_set_header参数设置
https://blog.csdn.net/summer_fish/article/details/117300072

proxy_pass http://172.31.5.0:5000;

proxy_set_header Host $host;
proxy_pass http://172.31.5.0:5000;

proxy_set_header Host $http_host;
proxy_pass http://172.31.5.0:5000;

202303

mysql

MYSQL解决 The total number of locks exceeds the lock table size 问题
https://blog.csdn.net/dingweiye123/article/details/80994576

show variables like "%tmp%";
SET GLOBAL  tmp_table_size =1024*1024*1024;

数据库血缘分析
https://github.com/reata/sqllineage

SQLLineage: 基于Python的SQL血缘分析工具
https://reata.github.io/blog/sqllineage-a-sql-lineage-analysis-tool/

SQLLineage v1.3:迈向字段血缘
https://reata.github.io/blog/sqllineage-towards-column-lineage/

Find the size of each index in a MySQL table
https://dba.stackexchange.com/questions/49656/find-the-size-of-each-index-in-a-mysql-table

How to estimate/predict data size and index size of a table in MySQL
https://dba.stackexchange.com/questions/46069/how-to-estimate-predict-data-size-and-index-size-of-a-table-in-mysql

SELECT
    CONCAT(FORMAT(DAT/POWER(1024,pw1),2),' ',SUBSTR(units,pw1*2+1,2)) DATSIZE,
    CONCAT(FORMAT(NDX/POWER(1024,pw2),2),' ',SUBSTR(units,pw2*2+1,2)) NDXSIZE,
    CONCAT(FORMAT(TBL/POWER(1024,pw3),2),' ',SUBSTR(units,pw3*2+1,2)) TBLSIZE
FROM
(
    SELECT DAT,NDX,TBL,IF(px>4,4,px) pw1,IF(py>4,4,py) pw2,IF(pz>4,4,pz) pw3
    FROM
    (
        SELECT data_length DAT,index_length NDX,data_length+index_length TBL,
        FLOOR(LOG(IF(data_length=0,1,data_length))/LOG(1024)) px,
        FLOOR(LOG(IF(index_length=0,1,index_length))/LOG(1024)) py,
        FLOOR(LOG(data_length+index_length)/LOG(1024)) pz
        FROM information_schema.tables
        WHERE table_schema='mydb'
        AND table_name='mytable'
    ) AA
) A,(SELECT 'B KBMBGBTB' units) B;

select database_name, table_name, index_name, stat_value*@@innodb_page_size
from mysql.innodb_index_stats where stat_name='size';

mysql 索引对 null 的处理

一个表 mytable 总共 100w 条数据,主键是 int unsigned 类型,索引列是 CHAR(50) 类型,下面是创建索引的语句。

create index ix_mytable_json_xxx on mytable ((JSON_VALUE(json, '$.xxx' RETURNING CHAR(50))));

其中 12572 条数据的 json->>‘$.xxx’ 有值,其余都是 NULL, 现在看 ix_mytable_json_xxx 索引占用空间 13 MB。

select database_name, table_name, index_name, stat_value*@@innodb_page_size/1024/1024 size_M
from mysql.innodb_index_stats
where stat_name='size' and  database_name='test' and table_name='mytable' and index_nam='ix_mytable_json_xxx';

假设每行数据在索引里占用 50+4 的话,需要 1000000*(50+4)/1024/1024=51.49 MB,这远远大于 13 MB,说明 mysql 的索引里是对 NULL有优化的。

data

Using pyarrow how do you append to parquet file?
https://9to5answer.com/using-pyarrow-how-do-you-append-to-parquet-file

Unfortunately, this cannot append to an existing .parquet file (see my answer that can). Reason: Once .close() is called, the file cannot be appended to, and before .close() is called, the .parquet file is not valid (will throw an exception due to a corrupted file as it’s missing its binary footer). The answer from @Contango solves this.

https://github.com/cldellow/csv2parquet/issues/13

The nature of the Parquet format is such that you can’t really update an existing file. (Wellllll, maybe it’s technically possible to do surgery and add new row groups and then update the footer. It’d require using relatively low-level APIs in the parquet library, though.)

linix

持续检查某个进程的 CPU 和内存占用

$ while true; do echo -n `date +'%H:%M:%S '`" ";ps -eo pid,%cpu,%mem,cmd | grep 'mysqld'| grep -v grep; sleep 1;done
03:22:55  3226830 39.6  4.0 /usr/sbin/mysqld
03:22:56  3226830 39.6  4.0 /usr/sbin/mysqld
03:22:57  3226830 39.6  4.0 /usr/sbin/mysqld
03:22:58  3226830 39.6  4.0 /usr/sbin/mysqld
03:22:59  3226830 39.6  4.0 /usr/sbin/mysqld
03:23:00  3226830 39.6  4.0 /usr/sbin/mysqld

java

Spring boot开启定时任务的三种方式
https://blog.csdn.net/qianlixiaomage/article/details/106599951

  • 第一种也就是最简单的一种:基于注解 (@Scheduled)的方式;
  • 第二种:基于接口 (SchedulingConfigurer);
  • 第三种:基于注解设定多线程定时任务。

Convert String to Hex in Java
https://www.delftstack.com/howto/java/string-to-hex-java/

// method 1
StringBuilder stringBuilder = new StringBuilder();

char[] charArray = str.toCharArray();

for (char c : charArray) {
    String charToHex = Integer.toHexString(c);
    stringBuilder.append(charToHex);
}

System.out.println("Converted Hex from String: "+stringBuilder.toString());

// method 2
import org.apache.commons.codec.binary.Hex;
import java.nio.charset.StandardCharsets;

byte[] byteArray = str.getBytes(StandardCharsets.UTF_8);
String convertedResult = Hex.encodeHexString(byteArray);

// method 3
byte[] getBytesFromString = str.getBytes(StandardCharsets.UTF_8);
BigInteger bigInteger = new BigInteger(1, getBytesFromString);

String convertedResult = String.format("%x", bigInteger);

System.out.println("Converted Hex from String: " + convertedResult);

linux

How to record reverse proxy upstream server serving request in Nginx log?
https://stackoverflow.com/questions/18627469/how-to-record-reverse-proxy-upstream-server-serving-request-in-nginx-log

log_format upstreamlog '[$time_local] $remote_addr - $remote_user - $server_name $host to: $upstream_addr: $request $status upstream_response_time $upstream_response_time msec $msec request_time $request_time';
access_log /var/log/nginx/access.log upstreamlog;

Experiments about a better locate using grep
https://a3nm.net/blog/better_locate.html

Approach	Time/query (s)  	Index size (MB)  
mlocate	5.5	300
GNU locate	4.6	75
grep	1.7	890
LC_ALL grep	0.7	890
LC_ALL grep (parallel)	0.3	890
LC_ALL grep (parallel) gzip  	1.3	105
LC_ALL grep (parallel) pigz  	1.0	105
LC_ALL grep (parallel) lz4	0.7	160

javascript

知识图谱项目前端可视化图论库——Cytoscape.js简介 DAG
https://www.cnblogs.com/zhilin/p/12074688.html

  • Cytoscape.js 是一个用原生JS编写的开源图论(又名网络)库。你可以使用Cytoscape.js进行图形分析和可视化。
  • Cytoscape.js 支持许多不同的图论用例。它支持有向图,无向图,混合图,循环,多图,复合图(一种超图),等等。

https://ourcodeworld.com/articles/read/159/top-5-best-free-diagrams-javascript-libraries
https://hackernoon.com/my-top-13-javascript-diagram-libraries-g2a53z6u

什么是Black-Litterman资产配置模型?
https://zhuanlan.zhihu.com/p/542122376

  • Black-Litterman 模型是一个关于投资组合配置(portfolio allocation)的贝叶斯模型(Bayesian model),它的初衷在于马科维茨(Markowitz)提出的现代投资组合理论(modern portfolio theory)在实际操作中的问题。
  • 在现代投资组合理论中,投资组合的最优权重是通过一个均值-方差最优化(mean-variance optimization)问题的求解得到的,而最优化问题中的资产预期收益率(expected returns)和协方差(covariances)都是给定的,它们不一定是对于预期收益率的合理估计。
  • 尤其在投资者对特定资产的未来表现持某些观点时,马科维茨均值-方差最优化给出的权重是不合理的。
  • 为解决此问题,Black-Litterman模型使用贝叶斯方法将投资者的观点纳入到对预期收益率的估计中。Black-Litterman模型有一个重要假设:所有资产收益率都遵循同样的概率分布(probability distribution)。

python

How could I use requests in asyncio?
https://stackoverflow.com/questions/22190403/how-could-i-use-requests-in-asyncio

import asyncio
import requests

async def main():
    loop = asyncio.get_event_loop()
    future1 = loop.run_in_executor(None, requests.get, 'http://www.google.com')
    future2 = loop.run_in_executor(None, requests.get, 'http://www.google.co.uk')
    response1 = await future1
    response2 = await future2
    print(response1.text)
    print(response2.text)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())


import asyncio
import aiohttp

@asyncio.coroutine
def do_request():
    proxy_url = 'http://localhost:8118'  # your proxy address
    response = yield from aiohttp.request(
        'GET', 'http://google.com',
        proxy=proxy_url,
    )
    return response

loop = asyncio.get_event_loop()
loop.run_until_complete(do_request())


import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
            'http://python.org',
            'https://google.com',
            'http://yifei.me'
        ]
    tasks = []
    async with aiohttp.ClientSession() as session:
        for url in urls:
            tasks.append(fetch(session, url))
        htmls = await asyncio.gather(*tasks)
        for html in htmls:
            print(html[:100])

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

浅度测评:requests、aiohttp、httpx 我应该用哪一个?
https://zhuanlan.zhihu.com/p/103711201

Make a Python asyncio call from a Flask route
https://stackoverflow.com/questions/47841985/make-a-python-asyncio-call-from-a-flask-route

How can I make python request module asyncio and aiohttp
https://stackoverflow.com/questions/75004160/how-can-i-make-python-request-module-asyncio-and-aiohttp

Making 1 million requests with python-aiohttp
https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html

AI

https://zhuanlan.zhihu.com/p/613155165

参考搜索引擎中“先检索再重排”的思路,针对文档问答设计“先检索再整合“的方案,整体思路如下:

  • 首先准备好文档,并整理为纯文本的格式。把每个文档切成若干个小的chunks
  • 调用文本转向量的接口,将每个chunk转为一个向量,并存入向量数据库
    • 文本转向量可以使用 openai embedding
    • 也可以使用其他方案,如 fasttext/simbert 等
  • 当用户发来一个问题的时候,将问题同样转为向量,并检索向量数据库,得到相关性最高的一个或几个chunk
  • 将问题和chunk合并重写为一个新的请求发给 openai api

sd 模型 webui
colab运行stable diffusion以及本地部署方法
https://zhuanlan.zhihu.com/p/561546984
https://blog.csdn.net/Kerry_Blue/article/details/128778005

国风
https://civitai.com/images/249208?modelId=10415&postId=119862&id=10415&slug=3-guofeng3
https://civitai.com/images/249210?modelId=10415&postId=119862&id=10415&slug=3-guofeng3

other

How to calculate cumulative sum / running total of a column in Excel?
https://www.extendoffice.com/documents/excel/5280-excel-calculate-cumulative-sum.html

=SUM($B$2:B2)
=IF(B2="","",SUM($B$2:B2))

条件 GPT 经验
https://c8xa9g10gh.feishu.cn/docx/SFnzdD0LqoM8kIxGVsrcAlRhn1d#SFnzdD0LqoM8kIxGVsrcAlRhn1d

202302

算法

为什么 360 面试官说 Trie 树没用?
https://www.zhihu.com/question/27168319

多模式匹配算法-AC算法等
https://blog.csdn.net/xiaof_90/article/details/77447625

问题一:如果有一个关键词,然后让你在一段长文本中找出这些关键词,如何做?
问题二:如果有10K个关键词,然后让你在一段长文本中找出这些关键词,如何做?

如上问题一中,一段长文本中找一个关键词,那么就是单模式匹配。除了朴素算法(暴力算法)之外,还有一些经典的算法,例如KMP算法等。
问题二中,一段长文本中找N个关键词,那么就是多模式匹配,除了朴素算法外,也有一些经典的算法,例如AC算法、BM算法等。

https://pypi.org/project/cyac/

>>> ac = AC.build([u"python", u"ruby"])
>>> for id, start, end in ac.match(u"python ruby"):
>>>     print(id, start, end)

适用于大规模的多关键字匹配的多模匹配算法

  • agrep 对处理大规模的多关键字匹配问题有高效。多模式中最著名的快速匹配算法之一。
  • MultiBDM 基于AC和DAWG两种自动机扫描思想的多模匹配算法。根据匹配过程中使用时可的不同,作者提出了两种改进。

python

获取异常信息

try:
    pass
except Exception as e:
    print getattr(e, 'message', repr(e))

Python性能分析工具Line_profiler
https://blog.csdn.net/weixin_44613728/article/details/120411325

Python代码优化工具——memory_profiler
https://blog.csdn.net/weixin_42245157/article/details/126623370

pip install line-profiler
pip install -U memory_profiler

def cpu_profiler():
    from line_profiler import LineProfiler
    p = LineProfiler()
    p.add_function(match_keywords)
    p_wrap = p(run)
    p_wrap()
    p.print_stats()

def mem_profiler():
    from memory_profiler import profile
    p = profile(precision=4)(run)
    p()

python ahocorasick介绍
https://blog.csdn.net/u010569893/article/details/97136696

ahocorasick 是个 python 模块,Aho-Corasick 算法是多模式匹配中的经典算法,目前在实际应用中较多。

  • Trie是一个字符串索引的词典,检索相关项时时间和字符串长度成正比。
  • AC自动机能够在一次运行中找到给定集合所有字符串。
  • AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配。

linux

Linux 内核 101:NUMA架构
https://zhuanlan.zhihu.com/p/62795773

proxy setting

bash <(curl -s -L https://git.io/v2ray.sh)
stress-ng -c 0 -l 30 -t 8640000000

mysql

带进度导入数据

pv database1.sql.gz | gunzip | mysql -uroot -p database1

字节面试:知道MySQL 的 NULL 值是怎么存放的吗?
https://blog.csdn.net/Javatutouhouduan/article/details/128150631

结果集行号

select @rowNum:=@rowNum + 1 AS '行号',a.username,a.money
from account a, (select @rowNum:=0) b

books

The Subtle Art of Not Giving a F*ck
https://book.douban.com/subject/26895197/

作者:易又饕(来自豆瓣)
来源:https://book.douban.com/review/10006306/

  • 第一,要区分“快乐”(happiness)和"快感"(high)。前者具有可持续性,能真正让生活变得美好。后者往往是短暂的生理刺激,在刺激结束后还可能带来更深的痛苦。
  • 第二,生活中充满了问题,因为问题本来就是生活的常态。不必为连绵不断的问题本身而感到苦恼,如果因为这些苦恼而纠结,我们必然就干不了其他事情,进而会为无所成就而进一步苦恼,陷入恶性循环。
  • 第三,快乐只有在解决问题的过程中才能获得,而从长期来看,逃避问题只能带来更多的压力和挑战。用追求快感的方式来逃避挑战,最后只能像喝海水解渴,越喝越渴。
  • 第四,既然痛苦和挣扎是人生不可避免的一部分,就应该时刻做好直面它们的准备。同时,要选择自己的战场,把精力、能力和毅力用到那些真正值得解决的问题上。
  • 第五,明白自己所在乎的价值,同时明白自己用以衡量这些价值的标尺是否真正合适。好的价值,是往往是自己可以掌控的、真实的并且不会伤害其他人。好的标尺,往往也不依赖于我们无法控制的他人评价。
  • 第六,真正能够持续带来快乐的,只有不断提升自我、不断达到目标、不断解决问题的过程,而任何存量指标,比如金钱的数量等等,一旦被我们达到,就不会再带来快乐了。
  • 第七,没有必要和别人比较。没有必要对自己感觉过于良好或者不好。有时候,我们觉得自己在某些方面表现平常,这本来就是生活的应有之义,接受就好。
  • 第八,与其抱怨自己没有灵感或者动力,不如直接上手去干事情。很多时候,灵感和动力是在劳动的过程中产生的。克服惰性与恐惧,踏踏实实开始行动,很多问题都会迎刃而解。
  • 第九,情感上的支持自有其意义和价值,但每个人的问题都要每个人自己去解决。亲密关系中最好的相处之道,不是施舍与依赖,而是坦诚与理解。
  • 第十,生命短暂,但生活充实的人在死亡面前就会变得坦然。我们所在乎的许多东西,在生命这个宏大的命题面前,可能根本就不值得为之纠结。我们要选择自己在乎什么。

AI

GPT in 60 Lines of NumPy
https://jaykmody.com/blog/gpt-from-scratch/

投资

在投资分析中,简单的往往是实用的。我的投资理念很简单:在好行业中挑选好公司,然后等待好价格时买入。与之相对应的投资分析工具也同样简单。

  • 波特五力分析。不要孤立地看待一只股票,而要把一个公司放到行业的上下游产业链和行业竞争格局的大背景中分析,重点搞清三个问题:
    • 公司对上下游的议价权
    • 与竞争对手的比较优势
    • 行业对潜在进入者的门槛。
  • 杜邦分析。弄清公司过去5年究竟是靠什么模式赚钱的(高利润、高周转还是高杠杆),然后看公司战略规划、团队背景和管理执行力等是否与其商业模式一致。例如,
    • 高利润模式的看其广告投入、研发投入、产品定位、差异化营销是否合理有效,
    • 高周转模式的看其运营管理能力、渠道管控能力、成本控制能力等是否具备
    • 高杠杆模式的看其风险控制能力、融资成本高低等。
  • 估值分析。通过同业横比和历史纵比,加上市值与未来成长空间比,在显著低估时买入。

这“三板斧”分别解决的是好行业、好公司和好价格的问题,挑出来的“三好学生”就是值得长期持有的好股票了。

javascript

js 爬虫
https://github.com/zloirock/core-js/blob/master/scripts/usage/usage.mjs

others

TL;DR: The Top 6 Text Summarization APIs
https://rapidapi.com/blog/top-text-summarization-apis/

随机卡通头像
Vanilla JavaScript Library For Creating Avatars On The Client or Server-Side
https://webcodeflow.com/avataaars-js

SQLite the only database you will ever need in most cases
https://www.unixsheikh.com/articles/sqlite-the-only-database-you-will-ever-need-in-most-cases.html
https://news.ycombinator.com/item?id=34812527

Goodbye, CSS-Tricks!
https://geoffgraham.me/goodbye-css-tricks/
https://news.ycombinator.com/item?id=34864701
https://css-tricks.com/snippets/css/a-guide-to-flexbox/

Write a First Person Game in 2KB With Rust
https://grantshandy.github.io/posts/raycasting/

数字人建模软件,有14天试用 https://www.agisoft.com/ Process digital images and generate 3D spatial data. Fast and highly accurate.

Deepfakes中文版,汉化版下载,各换脸软件下载(都已整理好)
https://blog.csdn.net/woniu211111/article/details/107901535
https://github.com/deepfakes/faceswap
https://blog.csdn.net/kaidikake/article/details/105224241

java

Bistoury原理解析
https://cloud.tencent.com/developer/article/1553180

Bistoury
去哪儿网开源的一个对应用透明无侵入的Java应用诊断工具,可以让开发人员无需登录机器或修改系统,就可以从日志、内存、线程、类信息、调试、机器和系统属性等各个方面对应用进行诊断,提升开发人员诊断问题的效率和能力。内部集成了arthas,所以它是arthas的超集。其中两个比较有特色的功能:在线DEBUG、动态监控,就是基于 Instrumentation + ASM 做的。

iBatis详解以及和MyBatis区别
https://www.iocoder.cn/MyBatis/x-plugins/

https://blog.csdn.net/zzuhkp/article/details/123518287

spring-boot-starter-parent 和 spring-boot-dependencies 都进行了依赖管理,如果依赖中存在漏洞我们就需要紧急进行修复,它们之间的升级方式有所不同。

  • 对于 spring-boot-starter-parent 而言,我们可以直接在 properties 中指定依赖的版本,因为在 spring-boot-dependencies 中包的坐标使用了这个属性值作为版本号
  • 对于 spring-boot-dependencies,如果要进行依赖升级,配置属性是不行的,需要在 spring-boot-dependencies 前面加上要升级的依赖的坐标
  • 如果要升级的依赖不是 spring-boot-starter-parent 或 spring-boot-dependencies 管理的依赖,还可以直接把它加到 dependencies 标签下,这样依据最短路径原则,我们直接配置的依赖会覆盖间接引入的依赖

202301

java

SpringCloud之Eureka详细的配置
https://www.cnblogs.com/BlogNetSpace/p/11264235.html
ubuntu 安装 rabbitmq
https://blog.csdn.net/sepnineth/article/details/126235964
搭建Eureka - 分区
https://blog.csdn.net/wxy540843763/article/details/100046858
Spring boot config 配置及刷新
https://blog.csdn.net/backonway/article/details/85094571
实体映射最强工具类:MapStruct 真香!
https://cloud.tencent.com/developer/article/1996748

mapstruct坑:Internal error in the mapping processor: java.lang.NullPointerException at org.mapstruct.
https://blog.csdn.net/qq_37132495/article/details/122010257

Setting -->Build,Execution,Deployment -->Compiler -->User-local build process VM options (overrides Shared options):
-Djps.track.ap.dependencies=false

解决 HikariPool-1 - Exception during pool initialization.问题
https://blog.csdn.net/qq_40369243/article/details/115818732

Spring Security 实战干货:用户信息UserDetails相关入门
https://segmentfault.com/a/1190000020628228?utm_source=tag-newest
spring-cloud-gateway之GlobalFilter
https://www.jianshu.com/p/55de48fc484b
SpringCloud:学习Gateway网关拦截器的ServerWebExchange
https://www.cnblogs.com/fdzang/p/11812348.html
统一认证中心 Oauth2 认证坑
https://blog.csdn.net/wangsofa/article/details/121155006
Spring Security OAuth2 单点登录
https://www.cnblogs.com/cjsblog/p/15512596.html
GateWay 中StripPrefix的作用
https://blog.csdn.net/pichcar1982/article/details/120427469
Spring Security Oauth2 ResourceServerConfigurerAdapter (资源服务器配置)
https://blog.csdn.net/wangooo/article/details/113924394
Spring Security OAuth2 Opaque 令牌的简单使用指南
https://blog.csdn.net/new_ord/article/details/127834421
springcloud — 微服务鉴权管理Spring Security OAuth2原理解析(五)
https://blog.csdn.net/qq_38658567/article/details/113249583
springboot以jar包运行
https://www.cnblogs.com/xiaohang123/p/14945194.html
如何在spring security手动自定义用户认证SecurityContextHolder设置Authentication?
https://blog.51cto.com/u_12004792/5786751

http://localhost:8611/auth-dev.yml
http://localhost:8611/auth/dev
http://localhost:8612/actuator/gateway/routes

前端

浏览器原生支持ES6 export和import模块
http://www.hlwen.com/2022/09/22/757.html

Node.js 如何处理 ES6 模块
http://www.ruanyifeng.com/blog/2020/08/how-nodejs-use-es6-module.html

vue项目多环境配置(.env)的实现
https://www.jb51.net/article/217747.htm

PWA超简单入门
https://juejin.cn/post/6844903584899792903
https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps
https://web.dev/progressive-web-apps/

尤雨溪:Turbopack真的比Vite快10倍吗?
https://blog.csdn.net/gtLBTNq9mr3/article/details/127680877

谈谈JS二进制:File、Blob、FileReader、ArrayBuffer、Base64
https://blog.csdn.net/qiwoo_weekly/article/details/127255281

webpack打包之sourcemap
https://blog.csdn.net/formylovetm/article/details/126095387

redis

一篇文章搞定Redis Stream
https://blog.csdn.net/lt_xiaodou/article/details/126525965

不管是list还是订阅/发布模式,都有其弊端,比如list不能友好的重复消费,需要重复消费的话,需要程序代码去控制;而订阅/发布模式是一种转发消息的模式,只有订阅者在线的时候才能接收到消息,订阅者不在线期间产生的消息,就丢掉了。而Stream,有借鉴Kafka一些市面上成熟的消息队列的思想,可以消费失败重复消费,消息是持久化的。

postgre

默认配置

$ cat ~/.psqlrc
\timing
\pset border 2

PostgreSQL中文文档
https://www.yiibai.com/manual/postgresql/index.html

linux

clear all iptables rules
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X

stress-ng: Simulate specific cpu percentages
https://serverfault.com/questions/796225/stress-ng-simulate-specific-cpu-percentages

I designed stress-ng so that one can specify 0 for the number of stressor processes to match the number of on-line CPUs, so to load each cpu at say 40%, use

stress-ng -c 0 -l 40

ssh 超时
https://www.bbsmax.com/A/MyJxnVG1dn/

服务端
vi /etc/ssh/sshd_config

    # server每隔60秒给客户端发送一次保活信息包给客户端
    ClientAliveInterval 60
    # server端发出的请求客户端没有回应的次数达到86400次的时候就断开连接,正常情况下客户端都会相应
    ClientAliveCountMax 86400

客户端
vi /etc/ssh/ssh_config

    # client 每隔60秒给客户端发送一次保活信息包给客户端
    ServerAliveInterval 60
    # client 端发出的请求服务端没有回应的次数达到86400次的时候就断开连接,正常情况下服务端都会相应
    ServerAliveCountMax 86400

How can I tail a zipped file without reading its entire contents?
https://stackoverflow.com/questions/1183001/how-can-i-tail-a-zipped-file-without-reading-its-entire-contents

No, you can’t. The zipping algorithm works on streams and adapts its internal codings to what the stream contains to achieve its high compression ratio.

Without knowing what the contents of the stream are before a certain point, it’s impossible to know how to go about de-compressing from that point on.

If it’s an option, then bzip2 might be a better compression algorithm to use for this purpose.

Bzip2 uses a block compression scheme. As such, if you take a chunk of the end of your file which you are sure is large enough to contain all of the last chunk, then you can recover it with bzip2recover.

How to get few lines from a .gz compressed file without uncompressing
https://stackoverflow.com/questions/8151380/how-to-get-few-lines-from-a-gz-compressed-file-without-uncompressing

gzip -cd CONN.20111109.0057.gz | head

zip, gzip, bzip2

  • gzip 只能压缩文件, 不能压缩目录, 后缀名为 .gz, 而且不保留原文件,还可以和 tar 命令一起构成 Linux 操作系统中比较流行的压缩文件格式。
  • bzip2 是gzip的升级版本,-压缩比比较高,- k 产生压缩文件后保留原文件

[译] 理解 zip 和 gzip 压缩格式背后的压缩算法
https://zhuanlan.zhihu.com/p/143459234

  • 虽然各种压缩算法适用于不同场景,但是它们的底层都是基于 DEFLATE。
  • DEFLATE 是同时使用了 LZ77 算法与哈夫曼编码(Huffman Coding)的一种无损数据压缩算法。
  • DEFLATE 最初是作为 LZW 以及其它受专利保护的数据压缩算法的替代版本而设计的。
  • 从技术上来说,zip 压缩格式是支持使用其他的压缩算法的,但是 DEFLATE 是其中最常用的一种。
  • zip 是一种相当简单的分别压缩每个文件的存档格式,分别压缩文件允许不必读取另外的数据而检索独立的文件。
  • zip 和 gzip(gz)不兼容,虽然它们都是使用相同的 deflate 压缩算法
  • zip 更像一个打包器,能把多个多件放到一个zip中;gzip 一次只对一个文件压缩,通常与 tar 命令一起用。
  • gz 的压缩速度更快,而 bz 的压缩比更好
  • GZIP 最早由 Jean-loup Gailly 和 Mark Adler 创建,用于 unix 系统的文件压缩,ZIP 文件格式是一种数据压缩和文档储存的文件格式。

Extract only a specific file from a zipped archive to a given directory
https://unix.stackexchange.com/questions/14120/extract-only-a-specific-file-from-a-zipped-archive-to-a-given-directory

unzip -l myarchive.zip
unzip -p myarchive.zip path/to/zipped/file.txt >file.txt
unzip -p myarchive.zip path/to/zipped/file.txt | head 
unzip -j "myarchive.zip" "in/archive/file.txt" -d "/path/to/unzip/to"
unzip -j myarchive.zip in/archive/file.txt another/file.ext -d /path/to/unzip/to
unzip -j archive.zip "sub/dir/*" -d "dest/dir"

I changed my hostname, why is my bash PS1 prompt unchanged?
https://unix.stackexchange.com/questions/15643/i-changed-my-hostname-why-is-my-bash-ps1-prompt-unchanged

echo 'mynewhostname' | sudo tee /etc/hostname
sudo hostname -F /etc/hostname
vi /etc/hosts
    127.0.0.1    mynewhostname.mydomainname.com    mynewhostname

SSH server gives “userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]” when connecting with Putty
https://unix.stackexchange.com/questions/721606/ssh-server-gives-userauth-pubkey-key-type-ssh-rsa-not-in-pubkeyacceptedalgorit

There are several types of keys and signature algorithms in the SSH protocol.
RSA keys, which have the key type ssh-rsa, can be used to sign with

  • SHA-1 (in which case, the signature type is ssh-rsa),
  • SHA-256 (which has signature type rsa-sha2-256),
  • or SHA-512 (which has signature type rsa-sha2-512).

backend

理解OAuth 2.0
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

Parquet 就是一种基于列式存储的文件格式,它有两个主要优点 [4]:

高度可压缩性:.json 或 .csv 文件通常默认未压缩,而 Parquet 会压缩数据,因此可以节省大量磁盘空间。表 通常包含具有大量唯一值的列(high cardinality(这里理解为出现次数多且值不同);例如用户 ID)和只有少数唯一值的列(low cardinality(虽然出现次数很多,但值都相同);例如国家)。频率越低,压缩效果越好(可能)——下一节将详细介绍。

文件查询/过滤下推:在读入之前修剪不必要的数据。这可以缩短加载时间并优化资源消耗。如果需要从一千个表中获取两列,你不需要扫描所有行来获取这两个属性——你直接获取整个这两列。

Arrow 序列化设计提供了一个“数据头”,它描述了表中所有列的所有内存缓冲区的确切位置和大小。这意味着你可以内存映射巨大的、大于 RAM 的数据集,并在它们上就地评估 pandas 风格的算法,而无需像现在使用 pandas 那样将它们加载到内存中。你可以从 1 TB 表的中间读取 1 兆字节,而只需支付执行这些总计 1 兆字节的随机读取的成本

下面这两个方式中需要进行权衡:

  • 优化磁盘空间/磁盘上的长期存储 → Parquet
  • 优化数据交换和快速检索 → Arrow

简单理解parquet文件格式——按列存储和元数据存储
https://blog.csdn.net/zhang35/article/details/122284903

Apache Arrow :零内存读取DataFrame
https://blog.csdn.net/qq_43232373/article/details/123995262

AWS 数据清洗技术栈

  • AWS S3 是一种对象存储服务,提供行业领先的可扩展性、数据可用性、安全性和性能。
  • Parquet 仅仅是一种列式存储格式,它是语言、平台无关的,并且不需要和任何一种数据处理框架绑定。
  • Apache Arrow 为平面和层次数据定义了一种与语言无关的柱状内存格式,这种格式的组织用于在现代硬件(如cpu和gpu)上进行高效的分析操作。pyarrow 是用于 Arrow 的 Python 库。
  • AWS Glue 是一项无服务器数据集成服务,它简化了发现、准备、移动和集成来自多个来源的数据以进行分析、机器学习(ML)和应用程序开发的工作。
  • Amazon Athena 是一种交互式查询服务,让您能够轻松使用标准 SQL 直接分析 Amazon S3 中的数据。

athena 的价格,扫描 1T 数据是5美元, 可以省钱的考虑点:

  • parquet 本身是压缩的,另外 athena 应该也支持压缩后的csv.gz格式。
  • parquet 是列数据库文件格式,如果查询语句里用不到所有列的话,一次查询可能不需要扫描整个文件,扫描量会少一些,这点比csv好。
  • parquet 支持分区,如果提前能知道以后可能的查询,可以设计好分区key,每次扫描可以继续减少扫描量。

mysql

mysql 排序,利用变量实现 显示排序序号
https://blog.csdn.net/weixin_55806809/article/details/122931550

  • “ := ” 赋值的意思 。 set 和 update 时, 但是一般都用 “ = ” 。 select 时 只能使用“ := ”方式
  • “ = ” set 和 update时 ,表示赋值。select 时 , 表示是判断。

code

set @i = 0;
set @sco = null;
select
student_id,
score,
case when @sco = score then @i else @i := @i + 1 end as 排名序号,
@sco := score
from tb_score where course_id = 1 ORDER BY score desc

SELECT sid,sname,gender,age,(@i:=@i+1) AS '序号'
FROM student,(SELECT @i:=0) AS itable;

MySQL 性能监控4大指标——第一部分
https://www.jianshu.com/p/36f385935ebd

Mysql Performance_schema简介, 表和常用性能查询
https://blog.csdn.net/solinger/article/details/122300008

哪类的SQL执行最多?

SELECT DIGEST_TEXT,COUNT_STAR,FIRST_SEEN,LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY COUNT_STAR DESC limit 10\G

哪类SQL的平均响应时间最多?
SELECT DIGEST_TEXT,COUNT_STAR,AVG_TIMER_WAIT,FIRST_SEEN,LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY AVG_TIMER_WAIT DESC limit 10\G

哪类SQL扫描记录数最多?
SELECT DIGEST_TEXT,SUM_ROWS_EXAMINED ,FIRST_SEEN,LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_ROWS_EXAMINED DESC limit 10\G

SELECT DIGEST_TEXT,ROUND((SUM(sum_timer_wait) / SUM(count_star)) avg_time,FIRST_SEEN,LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY ROUND((SUM(sum_timer_wait) / SUM(count_star))  DESC limit 10\G

SELECT * FROM sys.statements_with_runtimes_in_95th_percentile limit 10\G

SHOW GLOBAL STATUS LIKE "Questions";

SELECT schema_name
     , SUM(count_star) count
     , ROUND(   (SUM(sum_timer_wait) / SUM(count_star))
     / 1000000) AS avg_microsec

     FROM performance_schema.events_statements_summary_by_digest

 WHERE schema_name IS NOT NULL
 GROUP BY schema_name;

Find last query executed by specific session on MySQL server
https://dataedo.com/kb/query/mysql/find-last-query-executed-by-session

set global log_output = 'table';
set global general_log = 'on';
select *,CONVERT((argument) USING utf8) t  from mysql.general_log limit 10\G
set global general_log = 'off';

table operator

  • check table: 检查 InnoDB 和 MyIsam 是否有错误。检查表或者视图是否存在错误
  • optimize table: 恢复被删除的块和重组表,清理碎片
  • analyze table: 检测和重组表的关键字分布情况。用来分析和存储表的关键字的分布,使得系统获得准确的统计信息,影响 SQL 的执行计划的生成。
  • repair table : 修复表

MySQL中analyze table的作用是?生产上操作会有什么风险?
https://www.modb.pro/db/168442

一、analyze table的作用
1、analyze table 会统计索引分布信息。
2、对于 MyISAM 表,相当于执行了一次 myisamchk --analyze
3、支持 InnoDB、NDB、MyISAM 等存储引擎,但不支持视图(view)
4、执行 analyze table 时,会对表加上读锁(read lock)
5、该操作会记录binlog

二、生产上操作的风险
1、analyze table的需要扫描的page代价粗略估算公式:sample_pages * 索引数 * 表分区数。
2、因此,索引数量较多,或者表分区数量较多时,执行analyze table可能会比较费时,要自己评估代价,并默认只在负载低谷时执行。
3、特别提醒,如果某个表上当前有慢SQL,此时该表又执行analyze table,则该表后续的查询均会处于waiting for table flush的状态,严重的话会影响业务,因此执行前必须先检查有无慢查询。

算法

  • KMP:用于字符串的匹配问题,对于普通的做法需要O(n*m)的复杂度暴力匹配,一旦失配需要从这一次原串匹配的开头字符的下一个字符开始匹配,也就是意味着原串所正在匹配的位置 i 可能会一直回退。KMP复杂度O(m+n),KMP的做法就是保证了指向原串正在匹配的位置的i不会回退。

  • Trie树:(字典树,多模式串匹配算法)一种树形结构,它是一种专门处理字符串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串的问题(本质是利用字符串之间的公共前缀,将重复的前缀合并在一起)。

  • AC自动机:Trie树跟AC自动机之间的关系,就像单串匹配中朴素的串匹配算法与KMP算法一样,只不过前者针对的是多模式串。所以AC自动机实际上就是在Trie树之上,加了类似KMP的next数组,只不过此处的next数组是构建在树上。

202212

## windows

powershell 提示没权限,先用管理员模式启动

set-ExecutionPolicy RemoteSigned

linux

无法用 key ssh 到远程主机

journalctl -fu ssh
    userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]

vi /etc/ssh/sshd_config.
    PubkeyAcceptedAlgorithms=+ssh-rsa

sudo systemctl restart sshd

LVM

pv lv vg 介绍

  • PV(physical volume) 即物理卷,就是物理磁盘,可以通过 fdisk -l 查看操作系统有几块硬盘
  • VG(volume group) 即卷组,就是一组物理磁盘的组合,里面可以有一块硬盘也可以有多块硬盘
  • LV(logical volume)及逻辑卷,就是在 VG (指定的物理磁盘组)里面划分出来的
  • 可以说成是 PV 就是硬盘,而 VG 就是管理硬盘的操作系统,而 LV 就是操作系统分出来的各个分区.
  • PV->VG->LV-> 文件系统使用(挂载到某个目录)
  • 硬盘或分区做成 pv,然后将 pv 或多个 pv 建立 vg,vg 上建立 lv

git 配置

git config --global http.proxy http://127.0.0.1:10800
git config --global https.proxy https://127.0.0.1:10800

git config --global --unset http.proxy
git config --global --unset https.proxy

git config --global url."https://".insteadOf git://

git config --list --show-origin

fio 磁盘性能测试工具
https://www.cnblogs.com/lyhabc/p/16708771.html

dd 命令来测试性能,有如下问题:

  • dd 命令的 IO 模型单一,只能测试顺序 IO,不能测试随机 IO。
  • dd 命令可设置的参数较少,并且测试结果不一定能反映出磁盘的真实性能。
  • dd 命令的设计初衷就不是用例测试性能的,在 dd 的手册中可以看到。
  • 无法设置队列深度,因此不推荐用 dd 命令来测试最大读 IOPS。

fio 测试模板

#read 顺序读 吞吐量
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=read -size=10G -nrfiles=1 -filename=fio_readputth_test.txt -name='fio read test' -iodepth=2 -runtime=120 -numjobs=4 -time_based=1 -allow_mounted_write=1 -group_reporting

#write 顺序写 吞吐量
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=write -size=10G -nrfiles=1 -filename=fio_writeputth_test.txt -name='fio write test' -iodepth=2 -runtime=120 -numjobs=4 -time_based=1 -allow_mounted_write=1 -group_reporting


#read 顺序读
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=read -size=2G -nrfiles=1 -filename=fio_read_test.txt -name='fio read test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#write 顺序写
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=write -size=2G -nrfiles=1 -filename=fio_write_test.txt -name='fio write test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#readwrite 顺序混合读写
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=readwrite -size=2G -nrfiles=1 -filename=fio_readwrite_test.txt -name='fio readwrite test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#randread 随机读
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=randread -size=2G -nrfiles=1 -filename=fio_randread_test.txt -name='fio randread test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#randwrite 随机写
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=randwrite -size=2G -nrfiles=1 -filename=fio_randwrite_test.txt -name='fio randwrite test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#randrw 随机混合读写
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=randrw -size=2G -nrfiles=1 -filename=fio_randrw_test.txt -name='fio randrw test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

,对于小块io(以64k为界)只需要关注iops,平均时延(lat中的avg),大块io关注吞吐和平均时延(lat中的avg)即可

java

大白话讲解Spring的@bean注解
https://zhuanlan.zhihu.com/p/99870991

从广义上Spring注解可以分为两类:

  • 一类注解是用于注册 Bean,比如 @Component , @Repository , @ Controller , @Service , @Configration 这些注解就是用于注册 Bean,放进 IOC 容器中。
  • 一类注解是用于使用 Bean,比如 @Autowired , @Resource 注解,这些注解就是把屋子里的东西自己拿来用,如果你要拿,前提一定是屋子(IOC)里有的,不然就会报错。

Bean 注解

  • Spring 的 @Bean 注解用于告诉方法,产生一个 Bean 对象,然后这个 Bean 对象交给 Spring 管理。
    • 产生这个 Bean 对象的方法 Spring 只会调用一次,随后这个 Spring 将会将这个 Bean 对象放在自己的 IOC 容器中。
  • @Component , @Repository , @Controller , @Service 这些注解只局限于自己编写的类,
    • 而 @Bean 注解能把第三方库中的类实例加入 IOC 容器中并交给 spring 管理。
  • @Bean 注解的另一个好处就是能够动态获取一个 Bean 对象,能够根据环境不同得到不同的 Bean 对象。

Java随机生成RSA密钥对
https://blog.csdn.net/msq16021/article/details/123743361

SpringBoot Security 自定义登录页面
https://blog.csdn.net/weixin_42555971/article/details/127440094

基于数据库自定义UserDetailsService实现JWT认证
https://blog.csdn.net/lazy_LYF/article/details/127284982

单点登录SSO,JWT进行跨域身份验证,前端登录实现Coding在线(十一)
https://blog.csdn.net/wang121213145/article/details/123553741

SpringSecurity以及Oauth2(笔记)
https://blog.csdn.net/weixin_46949627/article/details/126698801

Spring MVC中redirect重定向3种方式(带参数)
https://blog.csdn.net/weixin_39973810/article/details/84847922

javascript

npm install 报错

  • git 挂代理:git config --global http.proxy http://127.0.0.1:10800
  • git 默认使用 http:git config --global url.“https://”.insteadOf git://
  • node-scss匹配的最高版本才nodjs 14,不能要最新版本的 nodejs
  • 跟linux还是windows没啥关系,linux也不行

其他

https://v2ex.com/t/901954 你们的 NAS 部署了什么有趣的服务?

  • 网盘:seafile,坚果云, dufs,filebrowser,baidunetdisk,timemachine,icloudpd,filebrowser
  • 文件同步:syncthing/nextcloud,etesync,icloudpd,samba
  • 照片:mt-photos,PhotoPrism,photoview
  • 内网穿透:cloudflared,frpc,tailscale
  • 内网组网:tailscale
  • 梯子:openclash,stashapp,subconverter,v2ray
  • 统一登录:authelia
  • 下载:aria2,aria2pro,qbittorrent
  • 搜索引擎:whoogle/searxng
  • 容器管理:portainer/watchtower
  • 密码管理:vaultwarden
  • 反代网关:traefik
  • git 仓库:gitea,Gogs
  • 网盘文件目录:alist
  • DNS:adguard-home,Adguard home DNS
  • 笔记博客:mastodon,outline,b3log/siyuan
  • 网站监控:uptime-kuma
  • RSS: rsshub,freshrss,ttrss
  • 智能家居:Home Assistant,doods2
  • 音视频:Jellyfin
  • 聊天:Snikket

笔记软件

需求

做一个单机不联网的笔记软件,能够

  • 编辑 markdown 文件
  • 编辑 excel, csv 文件
  • 编辑 word 文件
  • 画脑图
  • 画原型图
  • 画流程图
  • 画架构图
  • 画 uml 图
  • 画 ER 图
  • 涂鸦

开源组件

202211

linux

手把手教你使用VSCode进行linux内核代码阅读和开发
https://zhuanlan.zhihu.com/p/558286384

指定ssh key 克隆代码

git clone git@provider.com:userName/projectName.git --config core.sshCommand="ssh -i ~/location/to/private_ssh_key"

vscode 阅读内核源码配置

对比

  • source insight ,因为内核下有多个平台的头文件、源码,
    往往能找到很多个同名函数或变量的定义,还得一个一个去确认,非常麻烦。
  • vscode 加上 C++ Intellisense 插件或者 global 插件,类似source insight,
    需要手动排除未编译文件减小索引范围,代码定位不准。
  • 文本浏览工具和 grep 进行代码搜索浏览,这种方法最简单,效率也最低。
  • 使用 vim + ctags,比较高大上,但我觉得vim里打开很多文件不太方便,不太适合阅读大工程的代码。
  • vscode + remote ssh + clangd,clangd 插件用于代码语义分析、代码补全、跳转等。
    该方案克服了上面列举的几种方案的几乎各种缺点,能做到代码精准跳转、精准自动补全,

总体流程:

  • 安装 vscode
  • 安装 Remote SSH
  • 连接到远程 linux
  • 远程安装 clangd server
  • 本地安装 clange 插件
  • 配置 clangd 插件
  • linux 相关操作
  • 打开远程 linux 内核目录,等待 clangd 索引完毕
  • ctrl+t 查找符号,f12 查找定义,shift+alt+f12 查找引用,alt+箭头 编辑点跳转

clangd 插件配置

--compile-commands-dir=${workspaceFolder}
--background-index
--completion-style=detailed
--header-insertion=never
-log=info

linux 相关操作:

# 如果 vscode 远程无法安装 clang server,则手工安装
wget https://gitee.com/zhengqijun/clangd/releases/download/15.0.3/clangd-linux-15.0.3.zip

# 安装 bear,生成 compile_commands.json
sudo apt install bear
bear make bzImage ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

# 如果上面生成的 json 文件无效,再尝试下面的脚本
./scripts/gen_compile_commands.py

了解linux内核必读的五本书
https://zhuanlan.zhihu.com/p/359049747

  • 《Linux内核设计与实现》 简称 LKD,内容比较浅显易懂,个人认为是内核新人首先必读的书籍。
  • 《深入理解Linux内核》简称 ULK,相比于LKD的内容不够深入、覆盖面不广,ULK要深入全面得多。
  • 《Linux设备驱动程序》简称 LDD,驱动开发者都要人手一本了。
  • 《深入理解Linux虚拟内存管理》简称 LVMM,介绍Linux虚拟内存管理机制。
  • 《深入理解LINUX网络内幕》,讲解网络子系统实现的书。

pip3 报错

AttributeError: module 'lib' has no attribute 'X509_V_FLAG_CB_ISSUER_CHECK'

解决

apt remove python3-openssl -y 
apt autoremove

linux 命令示例速查
https://github.com/cheat/cheat
https://mp.weixin.qq.com/s/CEOU9LDSKU05uJSvgLSMZg

查看两个时间点之间的日志

sed -n '/2022-11-01T16:52:40/,/2022-11-01T16:52:42/p' /var/log/nginx/access.log | more

Linux sed命令完全攻略(超级详细)
http://c.biancheng.net/view/4028.html

mmap的几种使用场景
https://www.cnblogs.com/Arnold-Zhang/p/15686868.html
https://izualzhy.cn/mmap

mysql

JSON_TABLE - The Best of Both Worlds
https://dev.mysql.com/blog-archive/json_table-the-best-of-both-worlds/

查看长语句进度
https://www.lanmper.cn/mysql/t8551

select SQL_TEXT,ROWS_EXAMINED,ROWS_AFFECTED,ROWS_SENT, TIMER_WAIT/(1000*1000*1000) wait_ms, LOCK_TIME/(1000*1000*1000)

lock_ms from performance_schema.events_statements_current where SQL_TEXT is not null and TIMER_WAIT/(100010001000) > 100 order by TIMER_WAIT desc\G

  • TIMER_WAIT 事件经过的时间(持续时间),单位是皮秒(万亿分之一秒)
  • LOCK_TIME 等待表锁所花费的时间,该值以微秒为单位计算,但归一化为皮秒,以便与其他性能模式计时器进行比较。
  • ROWS_AFFECTED 语句影响的行数。
  • ROWS_SENT 语句返回的行数。
  • ROWS_EXAMINED 服务器层检查的行数(不计算存储引擎内部的任何处理)。

How to create index on json column in MySQL?
https://stackoverflow.com/questions/38389075/how-to-create-index-on-json-column-in-mysql

CREATE TABLE inventory(
items JSON,
INDEX i1 ( (JSON_VALUE(items, '$.name' RETURNING CHAR(50))) ),
INDEX i2 ( (JSON_VALUE(items, '$.price' RETURNING DECIMAL(5,2))) ),
INDEX i3 ( (JSON_VALUE(items, '$.quantity' RETURNING UNSIGNED)) )
);

SELECT items->"$.price" FROM inventory
WHERE JSON_VALUE(items, '$.name' RETURNING VARCHAR(50)) = "hat";

SELECT * FROM inventory
WHERE JSON_VALUE(items, '$.price' RETURNING DECIMAL(5,2)) <= 100.01;

SELECT items->"$.name" AS item, items->"$.price" AS amount
FROM inventory
WHERE JSON_VALUE(items, '$.quantity' RETURNING UNSIGNED) > 500;

postgre

内核 IO 参数
sysctl -a |grep vm.dirty_background_ratio

推荐配置

40 core, 80 thread @ 2.2Ghz
256GB RAM
16TB NVMe storage (RAID10 usable ~8TB), 28GB/s sequential read, 26GB/s sequential write, 4.9M random read IO/s, 4.4M random write IO/s

可视化执行计划

https://tatiyants.com/pev/#/plans

kill sql

# only select
SELECT pg_cancel_backend(PID);

# can be update, delete
SELECT pg_terminate_backend(PID);

show processlist

SELECT pid, datname AS db, query_start AS start, now() - query_start AS lap, query 
FROM pg_stat_activity 
WHERE state <> 'idle' and query not like '%pg_stat_activity%'  
and (now() - query_start) > interval '1 seconds';

理财

日内做多策略

  • 看 5 分钟级别 K 线
  • 低开,不做
  • 开盘第一条 K 线长上影线,中性,等待,观察第二根 K 线
  • 开盘光头大阳线,做多信号 +1
  • 前一日下午盘在均线上方运行,尾盘稳定,做多信号 +1
  • 前一日高波动震荡,做多信号 -1
  • 开仓后做动态止损,随着价格上升,提高止损位
  • 开仓后第一次斜率变缓不止盈,等待第二次拉升或跌到止损位
  • 开仓后出现震荡,持续 10 根 K 线不创新高后止盈出场
  • 二次拉升后斜率变缓后止盈出场
  • 连续 3 根光脚阴线后止损出场

python 蜡烛图
https://www.statology.org/matplotlib-python-candlestick-chart/
https://www.geeksforgeeks.org/how-to-create-a-candlestick-chart-in-matplotlib/
https://www.highcharts.com.cn/docs/candlestick

大数据

Flink 从 0 到 1 学习
https://github.com/zhisheng17/flink-learning
http://www.54tianzhisheng.cn/2018/10/13/flink-introduction/#

数据分层详解ODS、DWD、DWM、DWS、ADS
https://blog.csdn.net/qq_38730338/article/details/122713887

数据仓库

  • Data warehouse(可简写为DW或者DWH)数据仓库,是在数据库已经大量存在的情况下的一整套包括了etl、调度、建模在内的完整的理论体系。
  • 数据仓库的方案建设的目的,是为前端查询和分析作为基础。
  • 数据仓库并不是数据的最终目的地,而是为数据最终的目的地做好准备,这些准备包含:清洗、转义、分类、重组、合并、拆分、统计等

分层:

  • ODS: Operation Data Store 数据准备区,也称为贴源层
    • 经过抽取、洗净、传输,也就是ETL过程之后进入本层。
    • 为了考虑后续可能需要追溯数据问题,因此对于这一层就不建议做过多的数据清洗工作,原封不动地接入原始数据即可。
    • 来源:
      • 业务库:
        • 离线:sqoop 定时抽取数据;
        • 实时: 使用 canal 监听 mysql 的 binlog 日志
      • 埋点日志:
        • 离线:日志一般是以文件的形式保存,可以选择使用 flume 来定时同步;
        • 实时:spark streaming,Flink、Kafka
      • 消息队列:ActiveMQ、Kafka
  • DWD:数据细节层 data warehouse details
    • 业务层和数据仓库的隔离层,保持和ODS层一样的数据颗粒度
    • 主要是对 ODS 数据层做一些数据的清洗和规范化的操作,比如去除空数据、脏数据、离群值等。
    • 为了提高 ODS 的易用性,该层通常会才采用一些维度退化方法,将维度退化至事实表中,减少事实表和维表的关联。
  • DWM:数据中间层 Data Warehouse Middle
    • 对通用的核心维度进行聚合操作,算出相应的统计指标,提升公共指标的复用性。
  • DWS:数据服务层 Data Warehouse Service
    • 整合汇总成分析某一个主题域,用于提供后续的业务查询,OLAP 分析,数据服务等。
    • 该层的数据表会相对较少,一张表会涵盖比较多的业务内容,由于其字段较多,因此一般也会称该层的表为宽表。
  • ADS:数据应用层 Application Data Service
    • 一般会存放在 ES、Redis、PostgreSQL 供数据产品和数据分析使用的数据。
    • 也可存放在 hive 或者 Druid 中,供数据分析和数据挖掘使用,常用的数据报表应该存在这里。
  • Fact Table: 事实表
    • 指存储有事实记录的表,比如系统日志、销售记录等。
    • 事实表的记录在不断地增长,比如电商的商品订单表
  • Dimension Table:维表层
    • 与事实表相对应的一种表,它保存了维度的属性值,可以跟事实表做关联。
    • 相当于将事实表上经常重复出现的属性抽取、规范出来用一张表进行管理。
    • 高基数维度数据:一般是用户资料表、商品资料表类似的资料表,数量较大。
    • 低基数维度数据:一般是配置表,比如枚举字段对应的中文含义,或者日期维表等,数量较小。

https://blog.csdn.net/weixin_37536020/article/details/106815387
Spark DAG(Directed Acyclic Graph) 有向无环图

概念理解:

  • 一个 Transform 操作(即懒加载方法)转换成一个 RDD。
  • RDD 之间存在依赖关系,最后通过一个 Action 操作函数对数据进行计算。
  • 我们把 RDD 间组成的计算链,称为 DAG。
  • 通过 RDD 间的依赖关系,可以跟踪依赖链找到该分区的父分区,重新计算该分区数据,
    • 采用这种逆推父分区,恢复数据的方式,实现了 RDD 的容错机制。
  • Action 操作对应一个 Job 任务,根据依赖关系,将 DAG 划分为不同的阶段。
  • Task 对应一个分区,一个 Task 就是一个分区,RDD1 有 2 个分区,即 2 个 Task。

RDD 之间的依赖关系:

  • 窄依赖:
    • 父分区和子分区存在一对一的关系,比如:map 、filter、union函数。
    • 不会引入Shuffle的概念,不会发生磁盘 IO 读写。
    • DAG 中连续连续多个窄依赖,会放到一起执行。
  • 宽依赖:
    • 父分区和子分区存在多对多的关系,比如groupBy、sortByKey 等带分组功能函数。
    • 引入了 Shuffle 的概念,会发生磁盘 IO 读写。
    • 宽依赖数据丢失时,可以从 Shuffle 临时文件恢复数据

执行 Job 阶段划分过程:

  • Spark 在执行 Transformation 类型操作时,都不会立即执行,而是懒计算。
  • 执行若干步 Transformation 类型操作后,一旦遇到 Action 操作,才会真正触发计算。
  • 从当前 Action 往前回溯,如果遇到的是窄依赖则应用流水线优化,继续往前找,直到遇到一个宽依赖。
  • 依赖要进行 Shuffle,不执行流水线优化,所以将这一阶段执行过程组装为一个 Stage。
  • 再从当前宽依赖开始向前找,重复刚才的步骤,从而将整个 DAG 划分为若干 Stage。

一文学完Spark常用算子(Spark算子大全)
https://blog.csdn.net/u011109589/article/details/125675177

Spark 算子分为以下三类:

  • Value
    • 输入分区与输出分区一对一型: map flatMap mapPartitions glom
    • 输入分区与输出分区多对一型: union cartesian
    • 输入分区与输出分区多对多型: grouBy
    • 输出分区为输入分区子集型: filter distinct subtract sample takeSample
    • Cache: cache persist
  • Key-Value
    • 输入分区与输出分区一对一: mapValues
    • 对单个 RDD 或两个 RDD 聚集: combineByKey reduceByKey partitionBy
    • 两个RDD聚集: Cogroup
    • 连接: join leftOutJoin rightOutJoin
  • Action
    • 无输出: foreach
    • HDFS: saveAsTextFile saveAsObjectFile
    • Scala: collect reduceByKeyLocally lookup count top reduce fold aggregate
  • 转换算子
    • Value类型: 1. map 2. mapPartitions 3. mapPartitionsWithIndex 4. flatMap 5. glom 6. groupBy 7. filter 8. sample 9. distinct 10. coalesce 11. sortBy
    • 双Value类型: 1. intersection 2. union 3. subtract 4. zip
    • K-V类型: 1. partitionBy 2. reduceByKey 3. groupByKey 4. aggregateByKey 5. foldByKey 6. combineByKey 7. join 8. sortByKey 9. mapValues 10. cogroup
  • 行动算子 1. reduce 2. collect 3. count 4. first 5. take 6. takeOrdered 7. aggregate 8. fold 9. countByValue 10. countByKey 11. foreach 12. save

spark 下载
https://spark.apache.org/downloads.html
https://mirrors.tuna.tsinghua.edu.cn/apache/spark/

wget https://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-3.3.1/spark-3.3.1-bin-hadoop3-scala2.13.tgz
tar xf spark-3.3.1-bin-hadoop3-scala2.13.tgz
cd spark-3.3.1-bin-hadoop3-scala2.13
./bin/spark-shell --version

Spark:从“大数据的Hello World”开始
https://zhuanlan.zhihu.com/p/407652473

scala> import org.apache.spark.rdd.RDD
import org.apache.spark.rdd.RDD

scala> val rootPath: String = "."
val rootPath: String = .

scala> val file: String = s"${rootPath}/README.md"
val file: String = ./README.md

scala> val lineRDD: RDD[String] = spark.sparkContext.textFile(file)
val lineRDD: org.apache.spark.rdd.RDD[String] = ./README.md MapPartitionsRDD[3] at textFile at <console>:1

scala> val wordRDD: RDD[String] = lineRDD.flatMap(line => line.split(" "))
val wordRDD: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[4] at flatMap at <console>:1

scala> val cleanWordRDD: RDD[String] = wordRDD.filter(word => !word.equals(""))
val cleanWordRDD: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[5] at filter at <console>:1

scala> val kvRDD: RDD[(String, Int)] = cleanWordRDD.map(word => (word, 1))
val kvRDD: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[6] at map at <console>:1

scala> val wordCounts: RDD[(String, Int)] = kvRDD.reduceByKey((x, y) => x + y)
val wordCounts: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[7] at reduceByKey at <console>:1

scala> wordCounts.map{case (k, v) => (v, k)}.sortByKey(false).take(5)
val res0: Array[(Int, String)] = Array((23,the), (16,to), (15,Spark), (13,for), (9,##))

简化

text_file = sc.textFile("hdfs://...")
counts = text_file.flatMap(lambda line: line.split(" ")) \
             .map(lambda word: (word, 1)) \
             .reduceByKey(lambda a, b: a + b)
counts.saveAsTextFile("hdfs://...")

Spark和Flink的对比,谁才是大数据计算引擎王者?
https://blog.csdn.net/educast/article/details/119929704

Spark详解(02) - Spark概述
https://www.cnblogs.com/meanshift/p/16063784.html

Spark 集群的独立部署环境

  • 不需要依赖其他的资源调度框架,自身就实现了资源调度的功能
  • 环境中还有其他两个核心组件:Master 和 Worker
  • Master 是一个进程,主要负责资源的调度和分配,并进行集群的监控等职责,类似于 Yarn 环境中的 RM
  • Worker 也是进程,一个 Worker 运行在集群中的一台服务器上,由 Master 分配资源对数据进行并行的处理和计算,类似于 Yarn 环境中 NM。

ApplicationMaster

  • Hadoop 用户向 YARN 集群提交应用程序时,提交程序中应该包含 ApplicationMaster,
    • 用于向资源调度器申请执行任务的资源容器 Container
    • 运行用户自己的程序任务 job
    • 监控整个任务的执行
    • 跟踪整个任务的状态
    • 处理任务失败等异常情况。
  • 说的简单点就是,ResourceManager(资源)和 Driver(计算)之间的解耦合靠的就是 ApplicationMaster。

Yarn 环境

  • Client 和 Cluster,主要区别在于:Driver 程序的运行节点位置。
  • Yarn Client 模式
    • Client 模式将用于监控和调度的 Driver 模块在客户端执行,而不是在 Yarn 中,所以一般用于测试。
    • Driver 在任务提交的本地机器上运行
    • Driver 启动后会和 ResourceManager 通讯申请启动 ApplicationMaster
    • ResourceManager 分配 container,在合适的 NodeManager 上启动 ApplicationMaster,负责向 ResourceManager 申请 Executor 内存
    • ResourceManager 接到 ApplicationMaster 的资源申请后会分配 container,然后 ApplicationMaster 在资源分配指定的 NodeManager 上启动 Executor 进程
    • Executor 进程启动后会向 Driver 反向注册,Executor 全部注册完成后 Driver 开始执行 main 函数
    • 之后执行到 Action 算子时,触发一个 Job,并根据宽依赖开始划分 stage,每个 stage 生成对应的 TaskSet,之后将 task 分发到各个 Executor 上执行。
  • Yarn Cluster 模式
    • Cluster 模式将用于监控和调度的 Driver 模块启动在 Yarn 集群资源中执行。一般应用于实际生产环境。
    • 在 YARN Cluster 模式下,任务提交后会和 ResourceManager 通讯申请启动 ApplicationMaster,
    • 随后 ResourceManager 分配 container,在合适的 NodeManager 上启动 ApplicationMaster,此时的 ApplicationMaster 就是 Driver。
    • 后续和 Yarn Client 一样

spark-关于spark分区的理解
https://blog.csdn.net/qq_34224565/article/details/108556055

  • 确切的说,spark 没有分区,是 RDD 有分区。分区是 spark 在内存中进行并行计算时的一块独立的空间,是 RDD 并行计算的最小单元。
  • RDD 的数据集在逻辑上被划分为多个分片,每一个分片称为分区,而每个分区的数值计算都是在一个任务中进行的。
  • 任务的个数,也是由 RDD (准确来说是 job 最后一个 RDD)的分区数决定。
  • 数据源为 hdfs 时,rdd 的分区数由 hdfs 的 block 数决定,类似于 mr 的分片数跟 block 数相同,是考量了磁盘 IO 的性能后作出的选择。
  • 正常情况下,数据源为 hdfs 时,读取时是不需要设置分区数的,设置了反而会影响效率。
  • 分区数越多越好吗?
    • 分区数太多意味着任务数太多,每次调度任务也是很耗时的,所以分区数太多会导致总体耗时增多。
    • 如果一个分区的数据量过小,则 task 的调度会影响效率,如果分区数相对于 cores 过小,则会造成资源浪费。
  • 分区数太少会有什么影响?
    • 分区数太少的话,会导致一些节点没有分配到任务;
    • 分区数太少的话,会导致一些节点没有分配到任务;
    • 分区数不合理,会导致数据倾斜问题;
  • 官方建议 partitionNum 为 executor-cores * num-executor 的 2~3 倍。

分区方式
https://blog.csdn.net/dmy1115143060/article/details/82620715

  • Spark包含两种数据分区方式:HashPartitioner(哈希分区)和RangePartitioner(范围分区)。
  • 一般而言,对于初始读入的数据是不具有任何的数据分区方式的。
  • 数据分区方式只作用于<Key,Value>形式的数据。
  • 当一个 Job 包含 Shuffle 操作类型的算子时,如groupByKey,reduceByKey etc,此时就会使用数据分区方式来对数据进行分区
  • 在 Spark Shuffle 阶段中,共分为 Shuffle Write 阶段和 Shuffle Read 阶段
    • Shuffle Write 阶段中,Shuffle Map Task 对数据进行处理产生中间数据,然后再根据数据分区方式对中间数据进行分区。
    • Shffle Read 阶段中的 Shuffle Read Task 会拉取 Shuffle Write 阶段中产生的并已经分好区的中间数据。

Scala基础教程
https://blog.csdn.net/zzy979481894/article/details/123890912

其它

  • 俗话说:兔子不吃窝边草 可俗话又说:近水楼台先得月
  • 俗话说:宰相肚里能撑船 可俗话又说:有仇不报非君子
  • 俗话说:人不犯我,我不犯人。 可俗话又说:先下手为强,后下手遭殃。
  • 俗话说:男子汉大丈夫,宁死不屈。可俗话又说:男子汉大丈夫,能屈能伸。
  • 俗话说:打狗还得看主人  可俗话又说:杀鸡给猴看。
  • 俗话说:车到山前必有路  可俗话又说:不撞南墙不回头
  • 俗话说:礼轻情谊重        可俗话又说:礼多人不怪
  • 俗话说:人多力量大        可俗话又说:人多嘴杂
  • 俗话说:一个好汉三个帮  可俗话又说:靠人不如靠己
  • 俗话说:人往高处走        可俗话又说:爬的高,摔得重。

电路

德州仪器电路仿真 TINA-TI(TM)模拟器简介
http://training.eeworld.com.cn/TI/video/18813

整流电路
https://blog.csdn.net/cherrychen666/article/details/112986395

Tina-TI——小巧好用又高效的原理图仿真软件
https://zhuanlan.zhihu.com/p/437404464

  • TI 提供了很多仿真样例,包括音频、比较器、控制环路、电流环路、振荡器、功率放大器、传感器等等。
  • 仿真分析包括直流分析、交流分析、傅里叶分析、噪声分析等。
  • 直流分析可以用来测量某一些节点电压和直流传输特性等,如下可以测量某些节点的电压值。
  • 交流分析包括节点电压、振幅、相位、时延、奈奎斯特等。
  • 交流中分析bode图的幅频和相位曲线。
  • 测量工具包括常见的信号分析仪、示波器、XY记录器、函数发生器、万用表。

aws

ddb test

import boto3
from boto3.dynamodb.conditions import Key
ddb = boto3.resource('dynamodb')

test = ddb.Table('test')

print('insert data')
test.put_item(Item={'domain': 'hello.com', 'email': 'hao@hello.com'})
test.put_item(Item={'domain': 'hello.com', 'email': 'jimmy@hello.com'})
test.put_item(Item={'domain': 'gmail.com', 'email': 'onlytiancai@gmail.com'})

print('scan data')
response = test.scan()
for i in response['Items']:
    print(i)

print('query data')
response = test.query(
    KeyConditionExpression=(Key('domain').eq('hello.com') & Key('email').eq('hao@hello.com'))
)
for i in response['Items']:
    print(i)

print('delete data')
test.delete_item(Key={'domain': 'hello.com', 'email': 'hao@hello.com'})
test.delete_item(Key={'domain': 'hello.com', 'email': 'jimmy@hello.com'})
test.delete_item(Key={'domain': 'gmail.com', 'email': 'onlytiancai@gmail.com'})

DynamoDB基本概念
https://zhuanlan.zhihu.com/p/72397412

DynamoDB-二级索引
https://zhuanlan.zhihu.com/p/72610885

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。