0%

在使用单实例Redis时, 我们可以使用./redis-cli -h redis_ip -p redis 6379 --ldb --eval script.lua somekey , arg1 arg2命令轻松的进入debug模式调试lua脚本
在正常情况下, 进入debug模式后可以使用一系列命令来执行控制脚本的执行, 使用help命令应该可以看到如下界面

阅读全文 »

在使用Redis时, 通常会使用EXPIRE, PEXPIRE系列函数设置生存时间, 当需要获取超时时间时使用TTL, PTTL获取剩余的生存时间。

同样的, 还可以使用EXPIREAT, PEXPIREAT以unix timestamp格式设置超时时间点, 但需要注意的是, Redis 7.0 之前没有函数能获取设置timestamp, 只能使用TTL, PTTL获取剩余的生存时间。

在实际使用中, 经常需要比较新旧生存周期的大小来决定是否更新数据, 如果你很幸运的使用7.0及之后的版本, 可以使用EXPIREAT, PEXPIREAT配合GT参数来设置过期时间, 如果新的过期时间小于已有过期时间, 则会返回0

那么老版本的Redis该如何实现这种功能呢?

阅读全文 »

在terraform中,常见的输出json字符串或创建json文件的手段是使用流式标记, 如下代码所示:

1
2
3
4
5
6
7
8
9
10
11
12
resource "user" "admin" {
name = "admin"
}

resource "service" "portal" {
permission = <<DATA
{
"user": "${user.admin.name}"
"permission": "*"
}
DATA
}

但是这样的写法不仅繁琐,也容易出错,由于字符串中夹杂大量的变量引用,DATA标记中间的内容很难提供语法检查
常见的错误包括:

  • 最后一个元素不能带逗号
  • 引号及括号没有闭合
  • 夹杂中文字符

并且这些错误属于json语法问题,在terraform plan甚至apply期间是无法发现的,等到resource部署之后才被发现,可能会造成无法挽回的结果。

上述代码的json中便缺失一个逗号,读者是否有看出来呢?

为了解决这些问题,建议大家使用jsonencode函数代替直接编写字符串,得益于tf在语法上的良好兼容,从json迁移到jsonencode并不需要多少工作。

例如上述代码使用jsonencode可以简单的写成如下形式

1
2
3
4
5
6
7
8
9
10
resource "user" "admin" {
name = "admin"
}

resource "service" "portal" {
permission = jsonencode({
"user": "${user.admin.name}",
"permission": "*"
})
}

可以看到几乎就是简单的使用jsonencode讲原来的内容包了起来。

更进一步的,可以整理成如下形式

1
2
3
4
5
6
resource "service" "portal" {
permission = jsonencode({
user: user.admin.name,
permission: "*",
})
}

或者

1
2
3
4
5
6
resource "service" "portal" {
permission = jsonencode({
user = user.admin.name
permission = "*"
})
}

由于tf语法对逗号非常宽容,因此不论写不写逗号都不会影响输出的json,同时就算有语法错误,在plan阶段也可以轻易发现,还能少写很多引号。

因此推荐大家在输出json时都使用这种方法。

安装acme

1
curl https://get.acme.sh | sh -s [email protected]

使用阿里云dns认证方式

文档: https://github.com/acmesh-official/acme.sh/wiki/dnsapi

1
2
3
export Ali_Key="xxxxxxxxxxxxxxxx"
export Ali_Secret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
acme.sh --issue --dns dns_ali -d your.domain.com

安装密钥

1
acme.sh --install-cert -d your.domain.com --key-file /etc/nginx/your.domain.com.key --fullchain-file /etc/nginx/your.domain.com.pem --reloadcmd "sudo systemctl restart nginx"

在复制表时,可以使用CREATE-SELECT来同时复制表结构和数据

1
CREATE TABLE new_table SELECT  * FROM old_table;

但这样做实际上是有问题的

原因在于,CREATE-SELECT在创建新表时仅复制了字段类型,但是不会设置主键子增等属性。

因此,在复制表时,最好还是使用CREATE-LIKE和INSERT来复制

1
2
3
CREATE TABLE new_table LIKE old_table;

INSERT INTO new_table SELECT * FROM old_table;

由于早期数据库设计不合理,需要修改线上数据库表结构,比较麻烦的是新设计将原来的一个表拆成了两个表,并且允许了表之间存在一对多关系。

阅读全文 »

最近在写毕业论文,因为不断的修改添加了大量了引用,导致编号非常混乱,显得非常不美观,

又恰逢女朋友学校强制要求引用目录按照引用顺序排序,因此不得已开发了一个程序来对引用进行自动编号,

开发过程一波三折,难度也比一开始的设想大了很多,

因为需要处理书签引用和纯手写的引用,本来是想使用PyDocX的,测试后发现PyDocX读取书签引用有问题,

最后只能手写个简单的代码解析docx,虽然很麻烦但是总算是搞定了。

项目地址:https://github.com/Casxt/SortReference

阅读全文 »

现象描述

偶然发现一个线上服务不返回的badcase,在输入特定一张图片时,分析服务会直接断开连接而不返回任何数据,这种情况是非常罕见的,因为通常来说即便是内部服务报错的情况下,也会被框架捕获从而返回一组错误码,而不会直接断开连接不返回任何数据。

初步分析

考虑到这个现象可以被特定数据触发,且触发后业务依旧可以正常处理后续请求,因此认为是业务逻辑的问题,但是还不清楚业务逻辑是如何影响框架导致连接被关闭的。

初步调试

现象能稳定复现,应该是比较容易调试的,我首先将一台线上服务熔断,手动登录后打开日志调试。

请求后惊奇的发现业务逻辑没有任何报错,由于业务逻辑不是我写的,所以整个逻辑对我来说如同黑箱一样。

为了找到问题的原因,我将一张正常图片产生的日志和问题图片产生的日志都记录下来,并逐行对比,遗憾的是没有发现任何不同

再次分析

到这一步已经是山穷水尽了,因为通过日志打点分析,整个业务逻辑是正常return的,现在只能将目光转向框架层,但是遗憾的是框架层同样是一个黑箱,并且通过分析框架层的日志,也没有发现任何异常。

结合连接直接断开的现象,我怀疑框架层中的worker在返回请求时崩溃,并且被自动重启了。而导致崩溃的原因,只能是在业务逻辑中返回的response结构体上。

大胆猜测,是返回值被设置了特殊值导致框架层崩溃的。

再次调试

将设置response的代码全部注释后,果然可以正常返回空结构体,确认了之前的猜测。

之后通过二分注释的方法,确认了问题出在一个float字段上,当float字段被设置为Nan时,会导致无返回的现象发生,至此问题确认。

总结

protobuf本身是支持nan作为值的,因此是框架层自己的兼容性问题,但是这种一言不合就暴毙的问题排查,着实令人头疼。

一次写sql的时候,脑子发晕,把order by写成了sort by

在spark生态中

  • ORDER BY代表每个分片内部进行排序,使用后,会发现全部数据呈现局部有序性,详情可参考文档

  • SORT BY代表整体排序,它保证最后返回的数据是全部有序的,详情可参考文档