算法题 LEECODE 313. 超级丑数

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 题目 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/super-ugly-number 编写一段程序来查找第 n 个超级丑数。超级丑数是指其所有质因数都是长度为 k 的质数列表 primes 中的正整数。 示例 输入: n = 12, primes = [2,7,13,19] 输出: 32 解释: 给定长度为 4 的质数列表 primes = [2,7,13,19],前 12 个超级丑数序列为:[1,2,4,7,8,13,14,16,19,26,28,32]。 说明: 1 是任何给定 primes 的超级丑数。 给定 primes 中的数字以升序排列。 0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000 。 第 n 个超级丑数确保在 32 位有符整数范围内。 解题思路1 由于这是一道中等难度的题目,萌叔第一想到的是穷举,从1开始穷举,1、2 3、… N 判断每个数是否是超级丑数。这个思路肯定是没错的,结果提交后发现超时了。超时的原因是扫描了太多无用的数据。 ...

August 15, 2020 · 2 min

那些年我用过的WordPress插件

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 萌叔使用WordPress + Markdown的组合方式写blog已经有好几年了。在这篇文章中,笔者将会分享一些我曾经或者正在用的WordPress插件。 2. 插件 2.1 WP HyperMD Markdown编辑器,至今运行良好 对萌叔而言,用Markdown写文章写得更快,且不必要专注样式细节,而专注于内容本省。 2.2 Akismet Anti-Spam 反垃圾评论的,很好用 2.3 Cool Tag Cloud 一个简单但非常漂亮的标签云 效果如下图 2.4 Google XML Sitemaps 站点地图生成器,提高SEO效果。友情提示,别忘了将站点地图的地址提交给常用的搜索引擎。 本站的站点地图URI sitemap 2.5 Login LockDown 防止恶意程序采用暴力登录的方式,攻击网站。它的原理,如果来自某个IP的用户,在5分钟内连续3次登陆失败。将会禁止在未来的1个小时内,禁止来自这个IP的登录行为。 这个插件,萌叔非常推荐。如果你细心观察访问日志,来自互联网的恶意登录(主要是基于密码字典)非常普遍,使用Login LockDown可以增大恶意程序的攻击难度。另外建议用户名不使用"admin"、“root”, 密码一定使用强密码。 2.6 NoSpamNX 保护博客免受自动垃圾评论机器人的侵扰 2.7 WordPress Related Posts 它通过在内容页脚添加"相关推荐",提高整个网站的page view 效果形如 2.8 WP Super Cache WordPress的快速缓存插件 对动态页面进行静态缓存,可以抗一定量并发,并节约服务器资源。 2.9 Simple Google reCAPTCHA 借助Google reCAPTCHA,简单保护您的WordPress免受垃圾邮件评论和暴力攻击即可! 这个插件其实是个相当好的东西,相当于验证码的作用,可以阻止机器人的暴力攻击。不过由于墙的存在,导致这个插件依赖的JS文件经常加载失败,所以我把它禁用了。 2.10 Hide WP Login 由于wordpress的登录地址是固定的,所以很容易受到黑客的暴力登录的方式攻击。使用Hide WP Login可以隐藏网站的登录地址,或者要求访问登录页面时,比如携带特定的key。 ...

August 4, 2020 · 1 min

利用docker实现Golang程序的交叉编译

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 萌叔有有一个开源项目vearne/passwordbox,用于密码的管理。笔者想法是在Mac上build出多个平台下的bin文件,这样用户,可以无需自己编译,直接使用编译好的bin文件。 可是 vearne/passwordbox 内部依赖了 mattn/go-sqlite3。这个库编译时,依赖操作系统上的共享库,无法直接进行交叉编译。 2. 解决 前段时间,萌叔在阅读buger/goreplay源码时,偶然发现它有一个思路是利用docker来实现Golang交叉编译。于是笔者借鉴了它的思路,修改了passwordbox Makefile。 现在在Mac上执行 make docker-img # 只需要执行一次,生成基础镜像即可 make release 就可以同时生成Mac和linux下的bin文件 pwbox-v0.0.10-darwin-amd64.tar.gz pwbox-v0.0.10-linux-amd64.tar.gz 完整代码见Makefile 2.1 build一个基础镜像用于linux环境的编译 docker-img: docker build --rm -t $(CONTAINER) -f Dockerfile.dev . Dockerfile.dev FROM golang:1.14 RUN apt-get update && apt-get install vim-common -y WORKDIR /go/src/github.com/vearne/passwordbox/ ADD . /go/src/github.com/vearne/passwordbox/ RUN go get golang:1.14 实际是基于Ubuntu的一个镜像(Linux) 2.2 借助Docker实现跨平台编译 release-linux: docker run -v `pwd`:$(SOURCE_PATH) -t -e GOOS=linux -e GOARCH=amd64 -i $(CONTAINER) go build $(LDFLAGS) -o pwbox tar -zcvf pwbox-$(VERSION)-linux-amd64.tar.gz ./pwbox rm pwbox -v pwd:$(SOURCE_PATH) 是为了把项目的代码直接挂载到docker中,这样就无需每次拷贝代码到docker中 ...

August 3, 2020 · 1 min

istio学习笔记(2)-envoy

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 本文存在的目的,是为了通过图例的方式更好的整理envoy存在的意义 2. 图示 namespace配置了自动注入(istio-injection:enabled)之后,每个POD都会自动生成1个Sidecar容器 istio-proxy(运行sidecar代理,实现方式为Envoy或MOSN 图示展示服务网格中的请求的情况 2.1 请求网格内部的服务 downstream和upstream是网格内的2个服务的容器 downstream调用upstream 对这种场景,请求穿过需要穿过2个envoy,1个是调用方POD中的envoy, 1个是被调用方POD中的envoy 2.2 请求网格外部的服务 External Service是网格外部的1个服务 对于这种场景,只穿过一次envoy 3. 支持的服务治理功能 请求分发, 按不同版本,以特定权重分发 负载均衡 URL重写 故障注入,包含增加延迟,或者直接拒绝 服务熔断,比如针对5XX执行熔断操作 限频 重试 超时控制 状态统计 QPS/流量/URL/延迟等 这部分信息最后会由prometheus统一收集,最终展现在Grafana和Kiali中 envoy实际是将原来应用中的拦截器以及网关实现的部分功能做了抽取和抽象,使得应用开发人员能够转注于业务逻辑开发。 后记(重要) istio默认不记录日志。如果需要记录请求日志,需要在ConfigMap istio中,增加 accessLogFile: /dev/stdout accessLogEncoding: JSON # 可选值为 JSON或TEXT 另外envoy不支持HTTP1.0,如果发出的请求是HTTP1.0,会收到HTTP Status Code 426,要求升级协议。 参考资料 1.Sidecar 注入及透明流量劫持 2.Istio流量分析 打赏我

July 7, 2020 · 1 min

elasticsearch如何存储关联关系?

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 之所以写这篇文章是因为我已经在不止一个群里,看到有人问如何在ES中存储关联关系。 2. 答案 你可能会在网上看到有说Join datatype和Nested data type的,但是其实这都不是ES该有的玩法。 Join datatype和Nested data type都会涉及多次查询的开销 Join datatype本身的数据就是在不同的表中,对于分布式数据库,还涉及数据从不同的节点上拉取和组装的开销。 那么应该怎么做?答案就是用冗余的宽表来存储关联关系 举例说明 假如我需要在ES中存储的实体有书籍、书籍有作者信息、书名等等信息,显然实体之间有如下关系 如果在传统的关系型数据库中,就需要创建2张表,一张表表示作者,一张表代表书。但是对于nosql数据库,只需要一张表(书)即可,doc结构形如: { "name":"zhangsan", "publisher_identifier": "xxx-xxxx-xxx" "author":{ "name": "jobs", "phone": "111111111" } } 作者信息作为书的属性存储在一起,放一个doc中即可。 这样的做法必然是会带来数据冗余,但是以空间换时间,查询速度就有了保障。 现代的nosql数据库大多应对的海量数据的存储查询的问题,因此大都是分布式结构。在这种情况下,整体的设计方案必须足够简单,才能够易于维护和扩展。同样的做法,也完全适用于HBase。 3. 说几句某些人可能不爱听的话 ES集群的使用成本其实是很贵的,用了就别怕贵,觉得烧钱就别用 ES自身的性能优化工作做得还是很好的,对大多数人而言,不需要考虑优化,性能不够,就老老实实的加硬件就行。高版本相比低版本性能和稳定性都有很大的提升,优先考虑高版本 SSD对ES的性能提升非常明显(便宜不一定不是好货,但好货一定不便宜) 4. 参考资料 1.Join datatype 2.Nested data type 3.宽表和窄表的区别 打赏我

July 2, 2020 · 1 min

玩转高性能日志库ZAP (6)-采样

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 前言 uber开源的高性能日志库zap, 除了性能远超logrus之外,还有很多诱人的功能,比如支持日志采样、支持通过HTTP服务动态调整日志级别。本文简单聊一下日志采样。 使用说明 Sampling:Sampling实现了日志的流控功能,或者叫采样配置,主要有两个配置参数,Initial和Thereafter,实现的效果是在1s的时间单位内,如果某个日志级别下同样内容的日志输出数量超过了Initial的数量,那么超过之后,每隔Thereafter的数量,才会再输出一次。是一个对日志输出的保护功能。 注意 这里画个重点 仅对"同样内容" 的日志做采样 默认1s的时间单位内 示例 package main import ( "go.uber.org/zap" ) func main() { config := zap.NewProductionConfig() // 默认值:Initial:100 Thereafter:100 config.Sampling = &zap.SamplingConfig{ Initial: 5, // 从第6条数据开始 Thereafter: 3, // 每3条打印一条 } // 可以置为nil 来关闭采样 //config.Sampling = nil config.Encoding = "console" logger, _ := config.Build() defer logger.Sync() // 打印的消息要**重复**才会被执行采样动作 for i := 0; i < 100; i++ { logger.Info("hello") } } 输出 仅输出36条日志,而不是100条 ...

June 10, 2020 · 2 min

玩转KCP(5)-对比TCP

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 前言 本文将从功能特性上对比与TCP协议的差别。KCP有大量的思想借鉴了TCP的思想,最终得到的设计方案也与QUIC协议有很多的类同之处,很值得学习和研究。 特性对比 黄色表示新加的功能或者有较大的优化 绿色表示较小的优化 打赏萌叔

May 26, 2020 · 1 min

玩转KCP(4)-FEC(前向纠错)

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 xtaci/kcp-go的作者,在KCP标准协议的基础上做了扩展,增加了加密和FEC(Forward error correction,前向纠错)那么前向纠错到底是干什么用的 2. reed-solomon算法概述 在xtaci/kcp-go中,FEC的实现使用的是reed-solomon编码(实现库为klauspost/reedsolomon),这是一种诞生于上个世纪60年代的一种纠错码。详细的解释见参考资料1 原始数据如下图所示 它由4个piece组成, “ABCD” “EFGH” “IJKL” “MNOP”, 每行当做一个piece。 reed-solomon算法构造了一个编码矩阵(别问萌叔怎么构造,反正是挺深奥的数学问题),使得这个矩阵与原始矩阵相乘以后,得到的新矩阵。可以观察出来,新矩阵的前4个piece与旧矩阵完全相同,剩余的2个piece,被叫做parity, 权且翻译为校验块吧。 即使新矩阵丢失了2个piece 在等式2边乘以编码矩阵的逆矩阵,就可以消去编码矩阵,重新恢复出原始数据 3. reed-solomon算法结论总结 包含有n个symbol的消息可以通过reed-solomon算法,得到包含 n + k 个 symbol的新消息。任意丢失至多k个symbol,原始消息仍然能够被恢复出来。这里symbol和piece的概念类同。 因为reed-solomon算法的这个特性,它被广泛的用于 1)DVD、CD、二维码 碟片即使有部分被刮花,仍然能够播放 二维码即使部分被遮挡,仍然能够识别 2)远距离空间传输 空间探测器在向地球发送数据包时,每个包的传输可能需要耗费几个小时,传输过程中,极有可能由于其他陨石遮挡等原因,造成丢包。有了reed-solomon算法,丢失的包可以被直接恢复出来,不需要再重传。 3)存储系统,比如 minio 甚至萌叔发现它在 minio/minio 一个支持Amazon S3协议的对象存储系统中也有使用 缺点 增加了额外的存储和传输量,另外在做数据恢复时,有额外的计算开销。 4. FEC KCP协议中前向纠错相关的字段是这样设定的,它和块加密一样,都是可选的 FEC TYPE: typeData = 0xF1 原始数据块 typeParity = 0xF2 校验数据块 FEC SEQID: 递增的计数器 +-----------------+ | SESSION | +-----------------+ | KCP(ARQ) | +-----------------+ | FEC(OPTIONAL) | +-----------------+ | CRYPTO(OPTIONAL)| +-----------------+ | UDP(PACKET) | +-----------------+ | IP | +-----------------+ | LINK | +-----------------+ | PHY | +-----------------+ (LAYER MODEL OF KCP-GO) 注意 和网络分层模型一样,FEC只对自己这层负责,FEC对自己的数据包中到底存的是什么并不感兴趣。因此校验数据块中的数据应该被理解为2进制数据,它们是不能按照ARQ被解析的。 ...

May 25, 2020 · 2 min

玩转KCP(2)-流模式和消息模式

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 KCP协议包含了2中模式,消息模式和流模式。今天笔者来讲讲这2种模式的区别。 2. 流模式和消息模式 回顾一下KCP协议 0 4 5 6 8 (BYTE) +---------------+---+---+-------+ | conv |cmd|frg| wnd | +---------------+---+---+-------+ 8 | ts | sn | +---------------+---------------+ 16 | una | len | +---------------+---------------+ 24 | | | DATA (optional) | | | +-------------------------------+ frg:分片,用户数据可能会被分成多个KCP包,发送出去 在xtaci/kcp-go的消息模式实现不完整,这个字段始终为0 详见issues/121 sn: 序列号 len:数据长度(DATA的长度) data:用户数据 2.1 消息模式 假定一个场景,在IM中,A向B发送了一个消息,这个消息可能是文本消息,也可能是图片消息。那么应用程序发送的数据是有逻辑的消息的概念的。 kCP协议提供了一种能力把不同的消息(应用程序)划分在不同的KCP包中。 KCP定义 MSS的默认大小为1400 bytes,MSS(maximum segment size)表示最大段大小,它本身是TCP中的概念,表示包含TCP header,整个数据包的最大大小。在KCP协议中,概念类似,表示包含KCP header在内,整个KCP包的最大大小。 超过MSS的数据将会被拆分到成多个KCP包。根据是否拆包将会分成2种情况。 1)不拆包 3条消息Msg1,Msg2,Msg3分别包含在sn为 90、91、92的KCP包中 ...

May 11, 2020 · 1 min

玩转KCP(3)-流量控制

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 KCP协议的很多东西都是脱胎于TCP协议,所以他们在思想和实现上是完全相通的。xtaci/kcp-go 包含FEC也不过4000多行代码,skywind3000/kcp 主要是C/C++的代码,也就2000多行,萌叔建议大家都去阅读下源码。 慢启动、拥塞避免、拥塞发生、快速重传,这些概念都非常唬人,但看完代码你会发现不过尔尔。 在开始正式的文章之前,萌叔打算问几个问题? 流控是为了保护谁? 在实现中如何体现? 2. 流控是为了保护谁? TCP是全双工,这里简化一下,我们只看半双工的情况 Sender发送数据给Receiver 1) Sender中的应用程序把数据写入到本机的发送缓冲区 2) 数据从发送缓冲区写入到链路中,链路可能是由实际的光缆、电缆、多个路由器节点组成。 3)数据从链路转交到Receiver的接收缓冲区 4)数据从接收缓冲区交给Receiver的应用程序 发送缓冲区大小是有限的,它必须被保护起来 Sender和Receiver之间的链路的收发能力也是有限的,且是与网络中的其它节点共享的,因此Link也必须受到保护 接收缓冲区大小也是受限的,它也应该受到保护 3. 在实现中如何体现? 在实际实现中每一个需要保护的点,都有与之对应的参数,先上结论 3.1 使用发送端的发送窗口(snd_wnd)保护本机的发送缓冲区 3.2 使用拥塞窗口(cwnd)来保护发送端与接收端之间的链路 cwnd是动态变化的值, 算法与TCP协议基本相同 3.3 使用接收端的接收窗口(rmt_wnd, 表示接收窗口的空闲大小)保护接收端的接收缓冲区 rmt_wnd对应KCP协议的wnd, 由接收端汇报 回顾一下KCP协议 0 4 5 6 8 (BYTE) +---------------+---+---+-------+ | conv |cmd|frg| wnd | +---------------+---+---+-------+ 8 | ts | sn | +---------------+---------------+ 16 | una | len | +---------------+---------------+ 24 | | | DATA (optional) | | | +-------------------------------+ 4. 分析一次完整的写入动作 4.1 发送窗口和接收窗口对写入的影响 在KCP中,数据被拆分成Segment后 ...

May 10, 2020 · 3 min