上周,参加公司后端部门开发的分享。
在期间,该开发吐槽Redis好几个使用不便利的地方。
- Redis没有批量设置过期时间的命令
- incr 不存在的key的时候,并不会设置过期时间。导致持久化key的存在
作为客户端,解决办法只有使用lua脚本来进行实现:
思考
虽然说使用lua脚本也能够解决这样的问题,但是对用户体验不太友好,同时也增加了编码的复杂度。
而且这样的功能实现起来并不算复杂,为什么不可以在Redis服务端去实现这样的功能呢?
实现
说干咱就干。
利用周末的时间,简单的实现了其中的一个槽点功能:mexpire
可能会存在考虑欠缺的地方,但基本功能还是实现了的。
expire.c
expire.c
主要是对过期管理的文件。
一开始只想实现mexpire功能,结果发现还有expireta
、pexpire
、pexpirate
命令跟expire
命令相近,并且底层实现都是同一个函数。
于是就一起实现了。
逻辑其实很简单,就是遍历传过来的参数。
- 如果key存在,就设置过期时间。并计数。
- 如果key不存在,就跳过。
- 返回成功设置过期时间个数。
1 | void mexpireGenericCommand(client *c, long long basetime, int unit){ |
server.h
1 | void mexpireCommand(client *c); |
server.c
1 | {"mexpire",mexpireCommand,-3, "write @keyspace",0,NULL,1,-1,2,0,0,0}, |
这里有必要说明一下上面配置的解释。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20struct redisCommand {
char *name;
redisCommandProc *proc;
int arity;
char *sflags; /* Flags as string representation, one char per flag. */
uint64_t flags; /* The actual flags, obtained from the 'sflags' field. */
/* Use a function to determine keys arguments in a command line.
* Used for Redis Cluster redirect. */
redisGetKeysProc *getkeys_proc;
/* What keys should be loaded in background when calling this command? */
int firstkey; /* The first argument that's a key (0 = no keys) */
int lastkey; /* The last argument that's a key */
int keystep; /* The step between first and last key */
long long microseconds, calls;
int id; /* Command ID. This is a progressive ID starting from 0 that
is assigned at runtime, and is used in order to check
ACLs. A connection is able to execute a given command if
the user associated to the connection has this command
bit set in the bitmap of allowed commands. */
};
- name:命令名称
- function:指向函数
- arity:参数限制
- sflags:命令属性
- flags:命令属性掩码,一般为0
- get_keys_proc:在复杂参数下,指定那个才是真正的key。一般为NULL
- first_key_index:第一个参数所在位置
- last_key_index:最后一个参数所在位置
- key_step:命令步长
- microseconds:命令的度量项,由Redis来设置,并且总是初始化为0。
- calls:命令的度量项,由Redis来设置,并且总是初始化为0。
- id:命令的权限,由Redis来设置,并且总是初始化为0。
只需要修改以上几个文件然后启动就可以了。是不是很简单?
PS:前一篇文章中解决哨兵BUG《Redis哨兵client-reconfig-script脚本bug记录一则》时,调试就需要重新进行make && make install操作才行。
使用
命令使用,跟正常使用其他命令并没有什么太大区别。主要会跟mset
命令使用比较相似。
issue
本来还想去github提提issue的,结果发现早就有人跟作者提过这些问题了。我还是too yong to simple呀。
但是本着学习的心态,还是提了个issue,问问作者为什么不去实现这些简单又好用的命令。https://github.com/antirez/redis/issues/7263
后面有时间还是会继续实现其他命令的。