首页
关于作者
阅读记录
友链
Search
1
微内核插件架构风格在skywalking agent 上的实践
363 阅读
2
debian 11 安装nginx 并配置端口映射
341 阅读
3
和chatgpt聊设计
307 阅读
4
开始看《金阁寺》
246 阅读
5
github上star的工程分类记录
202 阅读
不知所云
杂记
书籍摘抄
有点技术
Redis
运维
架构
nginx
byzer
尚未分类
程序人生
与AI聊天
登录
/
注册
Search
标签搜索
nginx
redis
byzer
github
运维
mybatis-plus
王猪
累计撰写
25
篇文章
累计收到
3
条评论
首页
栏目
不知所云
杂记
书籍摘抄
有点技术
Redis
运维
架构
nginx
byzer
尚未分类
程序人生
与AI聊天
页面
关于作者
阅读记录
友链
搜索到
16
篇与
的结果
2023-06-09
redis big key 排查思路的奇思妙想
redis big key 排查思路的奇思妙想今天在秦晓辉的运维系统监控专栏交流群中,看到了几位朋友在讨论redis big key 扫描的方案。不自觉的来了兴致,参与了讨论。并且有一些比较奇特的思路。定义big key为了让对redis较为陌生的朋友不清楚big key的含义有一定的认知。我们先来定义一下Big Key。一切因为大,而导致redis去执行命令,网络传输而导致慢的key,都可以称为Big Key。一个String的值特别大一个List的元素特别多一个Hash的元素特别多List、Hash中某个元素特别大都可以称为Big Key。那具体,多大才算大呢?那其实要看你具体业务的容忍度了,并不是一个很严格的限制。这是我在知乎上看到一个博主对Big Key 大小的定义:一个STRING类型的Key,它的值为5MB(数据过大)一个LIST类型的Key,它的列表数量为20000个(列表数量过多)一个ZSET类型的Key,它的成员数量为10000个(成员数量过多)一个HASH格式的Key,它的成员数量虽然只有1000个但这些成员的value总大小为100MB(成员体积过大)我个人认为他对这个值度量定义的门槛颇低了,我目前开发维护的系统中,对一个String的Key,认为超过100KB就开始算大,超过1MB是严禁发生的。如何排查Big Key那如何排查Big Key呢?何时排查Big Key呢?一般情况下,我们应该在第一次上生产之前,对系统进行全面的各项测试,其中就应该包括Big Key 的排查。其次,就是在生产运行中,也许我们测试不够全面、也许多次迭代下来会有新的Big Key,我们应该由监控系统进行扫描排查。对于Big Key的排查来说,那应该就是把所有的Key,按照我们的阈值进行比对其占用的内存大小,判断其是否为Big Key。而我们知道,对于Redis 这种高性能内存缓存来说,我们都尽量使用一个O(1)算法复杂度的命令来调用,性能最佳。而全部Key进行扫描,显然是一个O(n)的复杂度,将会阻塞Redis 相当长的时间。而群里的讨论点在于:在压测的过程中,对redis big key进行扫描,并且尽量不影响性能。那让我们来看看传统的方案,以及个人的奇思妙想。官方解决方案在官方文档 Scanning for big keys中如下描述:In this special mode, redis-cli works as a key space analyzer. It scans the dataset for big keys, but also provides information about the data types that the data set consists of. This mode is enabled with the --bigkeys option, and produces verbose output.$ redis-cli --bigkeys # Scanning the entire keyspace to find biggest keys as well as # average sizes per key type. You can use -i 0.01 to sleep 0.01 sec # per SCAN command (not usually needed). [00.00%] Biggest string found so far 'key-419' with 3 bytes [05.14%] Biggest list found so far 'mylist' with 100004 items [35.77%] Biggest string found so far 'counter:__rand_int__' with 6 bytes [73.91%] Biggest hash found so far 'myobject' with 3 fields -------- summary ------- Sampled 506 keys in the keyspace! Total key length in bytes is 3452 (avg len 6.82) Biggest string found 'counter:__rand_int__' has 6 bytes Biggest list found 'mylist' has 100004 items Biggest hash found 'myobject' has 3 fields 504 strings with 1403 bytes (99.60% of keys, avg size 2.78) 1 lists with 100004 items (00.20% of keys, avg size 100004.00) 0 sets with 0 members (00.00% of keys, avg size 0.00) 1 hashs with 3 fields (00.20% of keys, avg size 3.00) 0 zsets with 0 members (00.00% of keys, avg size 0.00) 也就是使用redis-cli --bigkeys 命令进行扫描,并会按照strings、lists、sets、hashs、zsets统计。The program uses the SCAN command, so it can be executed against a busy server without impacting the operations, however the -i option can be used in order to throttle the scanning process of the specified fraction of second for each SCAN command.这个命令是通过SCAN指令进行实现的,并不是一次性直接对redis完成扫描,对于已经繁忙(处于)压测的服务器不会完全影响业务进行。但是实际上,也会有一定的性能影响。这个方案,也是这位测开朋友在压测时采用的方案。不过,他忽略了(当然,早期的客户端不一定支持这一参数)可以使用 -i 0.01参数可以更好的降低对redis服务器处理业务请求的影响。-i 0.01代表着redis-cli这一客户端在每执行一次SCAN指令后,会暂停0.01秒的时间。这一参数会导致big key 扫描本身耗时有一定增加,但是对redis服务器的压力就是降低许多,毕竟0.01秒对redis这种高性能的中间件来说,已经是一段不断的时间了。所以,就目前来说,最方便也最稳妥的方式就是redis-cli --bigkeys -i 0.01。解析RDB文件并统计RDB文件作为redis的一个全量持久化文件。通过下载并对他的解析统计Big Key,这对Redis服务器的资源则没有任何消耗,是十分合理的。但是若是为了扫描Big Key,在压测环境下执行BGSAVE这样的持久化指令,其fork进程的过程也会产生一定的阻塞,在Redis对他的标记上,也是@slow的。所以扫描一个已经产生的RDB文件是可取的,特意去持久化一次,理论上对Redis产生的阻塞也是不小的。那具体其耗时如何,也未进行实验验证。而这样的一个工具:redis-rdb-tools 在github上也拥有4.8K的star,想必使用的用户也是不少的。但是,我注意到了一点,这个工程最后一次提交在2020年。而截止目前,redis在其后已经相继发布了redis 6、redis 7等更高的版本,并且对于RDB文件的格式,在redis 7.0 已经更新到了format 10。这一“年久失修”的redis-rdb-tools 未必能够解析新版本的RDB文件。网络统计个人突发奇想,若是在网络层面上,通过抓包进行分析,对redis的TCP报文进行复制,然后使用Redis对应版本的RESP2、RESP3报文解析,不就可以分析这段时间内,客户端获取过的Big Key了吗?这样对redis服务器的CPU等资源就没有什么消耗了。当然,这个方案也有很明显的缺点,除了需要自行编写工具去分析以外,还存在很多分析不到的位置。例如一个LRANGE指令,对指定key的list进行范围扫描并返回:LRANGE key start stop它的复杂度是O(S+N),其中S的复杂度与列表的HEAD或者TAIL的距离有关,而N则是范围内元素的个数。所以当S很大,而N很小的时候,返回给客户端的数据量,其实还是小的,而它可能是一个Big Key,但是我们这个方案是没有机会发现它了。新增从节点个人觉得这是一个很妙的方式,具有可行性,但是也比较浪费,意义不是十分大的方案。我们可以在压测开始前,通过slave of 命令,将我们新起的一个redis节点作为压测节点的从节点。并且这个节点对应用不可见。那么我们在这个节点上进行big key的统计,就对业务没有任何影响了。总结官方提供的方式:redis-cli --bigkeys -i 0.01 应该是处理运行中的 redis big key 扫描的最佳方案了,当然,我们尽量避免高峰期去执行。不知道是否还有其他的方式进行Big Key 的扫描呢~附上今晚与太阳一同下班时,美丽的夕阳映照着河水产生金色氤氲的绝美画面,希望你也喜欢~
2023年06月09日
93 阅读
0 评论
0 点赞
2023-06-08
debian 11 安装nginx 并配置端口映射
debian 11 安装nginx 并配置端口映射问:Debian 11 x64 安装nginx 并配置 443 与80 映射到8080端口chatgpt的回答安装nginx并配置端口映射的步骤如下:安装nginx在Debian 11 x64上安装nginx可以使用以下命令:sudo apt update sudo apt install nginx安装完成后,nginx就会自动启动并监听80端口。配置端口映射为了将80和443端口映射到8080端口,需要修改nginx的配置文件/etc/nginx/sites-available/default。可以使用以下命令打开该文件:sudo nano /etc/nginx/sites-available/default在该文件中,找到以下两行:listen [::]:80 default_server; listen 80 default_server;将它们修改为:listen [::]:8080 default_server; listen 8080 default_server;然后,在该文件中再找到以下两行:listen [::]:443 ssl default_server; listen 443 ssl default_server;将它们修改为:listen [::]:8443 ssl default_server; listen 8443 ssl default_server;保存并关闭该文件。重启nginx配置完成后,需要重启nginx才能使配置生效。可以使用以下命令重启nginx:sudo systemctl restart nginx重启完成后,nginx就会监听8080和8443端口,并将它们映射到80和443端口。现在,您可以通过访问服务器的IP地址或域名来访问nginx服务器了,例如:http://your_server_ip/ https://your_server_ip/这些请求会被映射到8080或8443端口,并由nginx处理。实际的操作chatgpt 并不是万能的,存在错误和学习不及时。实际上,debian系安装的确如此apt install nginx 即可,不过生成的配置文件在/etc/nginx/nginx.conf。443端口是https的默认端口,还需要配置证书的,当然,修改配置文件后,重启生效是正确的。最简配置文件# 为注释,无需删除,不影响 #user www-data; worker_processes 2; #pid /run/nginx.pid; #include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; # multi_accept on; } http { # HTTP请求转发配置 server { listen 80; # 域名 server_name wangpig.life; location / { # 代理的IP:端口 proxy_pass http://wangpig.life:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } # HTTPS请求转发配置 server { listen 443 ssl; server_name wangpig.life; # 申请的证书所在的位置 ssl_certificate /root/zero-ssl-cert/certificate.crt; ssl_certificate_key /root/zero-ssl-cert/private.key; location / { proxy_pass http://wangpig.life:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } 遗漏的操作开通网络规则,或者关闭防火墙。没有关闭防火墙会导致外部无法访问。而本机通过curl则可请求得到响应。因为忘记修改防火墙,导致我这个nginx新手以为配置错误,查了好久,是有点菜了。在 Debian 11 上,可以使用以下命令来关闭防火墙:如果你使用的是 UFW 防火墙,可以使用以下命令来关闭它:sudo ufw disable如果你使用的是 iptables 防火墙,可以使用以下命令来清空规则并关闭它:sudo iptables -F sudo iptables -X sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT sudo iptables-save > /etc/iptables/rules.v4 sudo systemctl stop iptables sudo systemctl disable iptables请注意,关闭防火墙会使你的系统更加容易受到攻击,因此建议在必要的情况下才关闭防火墙。如果你需要在特定端口上打开流量,请确保只允许必要的流量通过,并使用其他安全措施来保护你的系统。
2023年06月08日
341 阅读
0 评论
0 点赞
2023-06-08
完整搭建个人博客的大致记录
完整搭建个人博客的记录说起搭建个人博客的原因,根本原因是CSDN方式我不是很喜欢,一堆广告,没经过验证的博客就可以往上面写,看着也心烦。遇上这次618活动,服务器打折,直接就是买买买。博客选型肯定不用静态博客,如果要用静态博客,直接github page或者gitee page 就完事了。动态博客,最著名最大的应该是WordPress,插件、主题都很多,功能十分丰富。然而乱花渐欲迷人眼,对小白不是很合适。Typecho 轻量,主要支持写markdown的朋友们,主题支持也是相当棒的。我最终选择的也是这款。部署按照官网推荐即可。当然,我这里是直接用了腾讯云的镜像,开机即可用。主题选择我曾经推荐的是 Twenty Fourteen但是呢,与其他一些主题一样,它的文章宽度太小,支持的设置也很少,代码格式也不可以调整。现在已经切换到JOE,宽度很不错。我FORK后做了一点点小修改。https://gitee.com/wanglhup/Joe将其放到对应的themes目录中,在Typecho 后管中即可切换,无需重启。购买服务器购买服务器上,国内主要还是阿里云、腾讯云、华为云等等,国外的话选择较多,amazon,oracle,vultr等等。不过为了国内用户访问快速稳定,我选择了国内。(这是一条相对麻烦的方式)我以腾讯云为例,乘着活动购买2c4g5m配置的服务器。为了避免广告之嫌疑,我就不上什么链接了,其他厂商也很棒!购买域名、配置证书这里就需要注意了,如果在国外购买了域名,你是没这么容易解析到自己国内的服务器上的,因为国外购买域名可以不用备案。但是你配置解析到国内服务器时,会被对应的云厂商拦截。所以,我在购买一个之后,发现了这个问题。。。然后我就在腾讯云中再次购买了一个类似的域名,也就是现在的wangpig.cn。对于一个HTTPS协议来说,还是需要一个CA机构颁发的证书的,这些在腾讯云的引导下,也是可以在控制台完成的。如果是自己操作,就需要手动去申请CA证书,然后上传到服务器的目录之下,然后再修改nginx的配置,也并不难。域名备案、网站备案在域名解析验证通过后,没过多久,腾讯云又会拦截你。因为你网站也是需要备案的!这里我就不详细展开讲了,因为腾讯云文档已经足够的完善,引导的也很好。而且我这儿讲了,后续手续变化也是可能存在的。要说的就是,没有必要请什么备案管家,普通性质的网站备案并不麻烦。只要按照流程填写即可,仅需要注意的是,你的备案网站名中不可以包含你的域名。就因为这个被腾讯云发回过一次。之后就是腾讯云通过后,提交管局。这是一个漫长的过程,大概是真的和官网说的那样,10天左右。浙江这边备案完成,是会给你发短信提示的。公安备案在域名、网站备案完成后,腾讯云完成同步,此时你已经可以使用域名访问到你的主机了。但是他也会提醒你,需要在30日内在当地公安完成备案,这也不需要外出去备案,同样是网上完成。之后将备案号写在网站底部即可。PS对于一个懂点linux的人来说,建站部署是比较轻松的,即使我不懂php和js。麻烦还是流程上的事。如果是国外的服务器与域名,大概1天就可以完成部署,再调整1-2天,博客就是你个人的模样了。
2023年06月08日
101 阅读
0 评论
0 点赞
2023-06-04
和chatgpt聊设计
和chatgpt聊设计chatgpt最近红的出圈,那我们就以自己负责的专业问题对他进行提问,聊一聊关于低代码SQL生成的设计。问问题的思路梳理了一下和chatgpt聊的思路:开门见山,限定范围,明确业务场景你好,我想要为低代码或者无代码的OLAP平台设计一个SQL NODE 类,它应该如何设计找准问题点,要求其修改,完善“query"还需要人传入SQL,并不符合低代码的需求。掌握整体,约定接口,数据结构我想知道的是具体如何完成低代码、无代码的设计。前端可视化界面应该传入哪些参数,又如何构建SqlNode。不断追问细节根据你的设计,查询对象的数据结构应该如何?给出专业的提示,往结果中增加内容,让chatgpt填充它画的大饼你用到的属性太少了,既然是OLAP,肯定还有许多聚合函数那如果聚合后还需要having支持呢?那如果是复杂的查询,有子查询呢?那除了子查询,我们还有连表查询?反复纠错,细化设计getJoinCondition 中是不是过于简单,如何表示 tableA.cloumn_a = tableB.column_b不断循环,给他提示,给他纠错你对SQL模型的把控不够精确,有些可以是复数的输入引申扩展,结合开源你是否知道apache calcite那我们的设计和calcite可否集成优化那SQLNode如何转成RelNode或RexNode,两者有何区别设计一下具体的转换过程输出结果那将这次设计有所的类,用UML类图描述一下给我你的图化的太难看了,用plantText的展示的语言描述你把我们设计里的属性、方法等也填充进来对应的java代码和注释也生成一份吧。结果展示类图:java代码:import java.util.List; class SQLNode { // SQL节点的基类 } class QueryObject { private List<SQLNode> nodes; public void addNode(SQLNode node) { // 将SQL节点添加到列表中 } public void buildQuery() { // 构建查询逻辑 } } class FilterCondition { private SQLNode child; private String condition; public SQLNode getChild() { // 获取子节点 } public void setChild(SQLNode child) { // 设置子节点 } public String getCondition() { // 获取筛选条件 } public void setCondition(String condition) { // 设置筛选条件 } } class AggregationCondition { private SQLNode input; private String aggregationFunction; public SQLNode getInput() { // 获取输入节点 } public void setInput(SQLNode input) { // 设置输入节点 } public String getAggregationFunction() { // 获取聚合函数 } public void setAggregationFunction(String aggregationFunction) { // 设置聚合函数 } } class SortCondition { private SQLNode child; private String sortField; public SQLNode getChild() { // 获取子节点 } public void setChild(SQLNode child) { // 设置子节点 } public String getSortField() { // 获取排序字段 } public void setSortField(String sortField) { // 设置排序字段 } } 总结总的来说,它的设计能力、反应能力的确是超过没有什么工作经验的工程师的,但是它仍然需要一个正确的方向引导,才能找到你要的方向。这样的聊设计的过程,大概持续了30多分钟 ,我省略了一些细节追问上的提问。具体的问答,可以见此聊天记录链接:https://chat.openai.com/share/0014f7c7-b911-46eb-821a-f9327642a163它设计的不一定对,但是大方向却并没有什么错误,在后续的编码设计过程中,有细节还可以继续追问。
2023年06月04日
307 阅读
0 评论
0 点赞
2023-06-03
属实懒人操作,用Stream Web,可以一个PO类就省略mvc+dao开发
Stream Web:简化后端开发的利器https://gitee.com/wanglhup/stream-web什么是 Stream WebStream Web 受到 Stream Query 项目的启发,它通过定义一个数据库持久层对象(PO),自动生成相应的基础 RESTful 接口,使得简单的增删改查操作变得更加便捷。已经支持以下接口实现: @GetMapping("/{entity}/{id}") public Object getById(@PathVariable("entity") String entity, @PathVariable("id") String id); @DeleteMapping("/{entity}/{id}") public void deleteById(@PathVariable("entity") String entity, @PathVariable("id") String id); @PostMapping("/{entity}") public int create(@PathVariable("entity") String entity, @RequestBody Object entityObject); @PutMapping("/{entity}") public int updateById(@PathVariable("entity") String entity, @RequestBody Object entityObject); @GetMapping("/{entity}/all") public List<Object> getAll(@PathVariable("entity") String entity); 其实现可见:org.dark.web.AutoGenApi用起来真的方便吗?Stream Web 基于 Stream Query 进行开发,只需要依赖 stream-web-core 并配置需要扫描的 PO 包名,即可轻松实现功能。您可以通过以下 Maven 依赖配置将 stream-web-core 引入到您的项目中:<dependency> <groupId>org.dark</groupId> <artifactId>stream-web-core</artifactId> <version>1.0-SNAPSHOT</version> </dependency>同时,您还需要在您的应用程序配置中添加以下配置项,以指定需要扫描的 PO 包名:stream-web: base-packages: org.dark.streamweb.demo.po请将上述配置项添加到您的应用程序的配置文件中(比如 application.yaml 或 application.properties)。将 org.dark.streamweb.demo.po 替换为您实际的 PO 包名,以确保 Stream Web 正确扫描并生成相应的 RESTful 接口。请将上述配置项添加到您的应用程序的配置文件中(比如 application.yaml 或 application.properties)。将 org.dark.streamweb.demo.po 替换为您实际的 PO 包名,以确保 Stream Web 正确扫描并生成相应的 RESTful 接口。DEMO定义了一个PO@Data @TableName("users") public class UserPO { @TableId(value = "pk_id", type = IdType.AUTO) private String id; @TableField("name") private String name; @TableField("email") private String email; } 这是它对应的建表语句:CREATE TABLE users ( pk_id INT NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, PRIMARY KEY (pk_id) ); -- 初始化三条数据 INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'); INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com'); INSERT INTO users (name, email) VALUES ('Charlie', 'charlie@example.com'); commit; 启动项目并访问浏览器访问,或者发送一个curl请求:curl http://localhost:8080/auto-gen/users/2就能得到一个json相应:{"id":"2","name":"Bob","email":"bob@example.com"}那它有什么问题吗?然而,目前的 Stream Web 只是一个玩具工程,它将所有接口都暴露给前端,没有进行鉴权的情况下,可能会导致被人拖库和删库等安全问题。因此,在将 Stream Web 用于实际项目中时,我们需要注意加强安全措施,包括但不限于鉴权机制和访问权限的限制,以确保数据的安全性。尽管 Stream Web 目前还存在一些问题,但它作为一个简化后端开发的工具,依然具有巨大的潜力。随着项目的不断演进和改进,相信 Stream Web 能够成为开发人员的得力助手,提升开发效率,减少重复工作,从而更好地服务于开发者和用户的需求。
2023年06月03日
126 阅读
0 评论
0 点赞
1
2
3
4
浙公网安备 33020502001051号
浙ICP备2023015387号-1