哈喽,大家好,我是一条。
Redis 作为一种非关系型数据库,以 key , value 的形式存储数据。这使它的查询复杂度为 O(1) 。
其中 key 永远是 string 类型,我们所说的 Redis 数据类型 其实是指 value 类型。
Redis 共有 5 大基本数据类型:string(字符串)、hash(哈希)、list(列表)、set(集合)及 zset (有序集合)。
随着版本更新,又增加了 Geo 、hyperloglog 、bitmap。
本文主要介绍 string 的一些命令和应用,下一篇会解读 string 类型的源码。
推荐一个网站,可作为 Redis 命令速查手册:http://doc.redisfans.com/
string 类型用 Java 语言来说就是 Map<String,String>
,是使用最为广泛的类型。
前面在安装时为大家演示过set k1 abc
,这其实就是添加了一个 string 类型的键值对。get k1
就是查询,类似 Java 中的 set、get 方法。
那么如何修改呢?只需要重新赋值即可。
> set k1 abcd
OK
> get k1
abcd
思考🤔一个问题:
如果我此时
set k2 abcd
,类比 Java 的 String 类型,会不会在内存再存储一份abcd
? 下一节分析源码时会讲到。
言归正传,如果我想拼接两个字符串怎么办?append
帮我们实现。如果 key 不存在,会报错。
> append k1 ef
6
> get k1
abcdef
> append k3
ERR wrong number of arguments for 'append' command
再思考🤔一个问题:
append k1 ef
后返回一个6,猜测应该是字符串的长度,那是怎么计算的呢,每次都for
循环吗? 同样分析了源码就恍然大悟了。
计算长度:strlen
> STRLEN k1
6
自增自减,即Java中的i++,i--
,如果是非数字的字符串会报错。
> set k3 12
OK
> INCR k3
13
> decr k3
12
> incr k1
ERR value is not an integer or out of range
再再思考🤔一个问题:
同样是 string 类型, Redis 是怎么知道是不是数字的? 同样分析了源码就恍然大悟了。
过期时间:即到时间自动删除。ttl
查看剩余时间, -2 代表已过期,-1 代表永不过期。
> setex k4 20 v4
OK
> ttl k4
16
> ttl k4
12
> get k4
null
> ttl k4
-2
> ttl k1
-1
还剩直接删除了,del
搞定
> del k1
1
> get k1
null
关于string 的命令其实还有,可以到我推荐的网站详细阅读,下面我们聊聊 string 的应用。
不需要高并发,也不需要大数据,就是平平无奇的一个缓存,也可能带来大的提升。
思考这样一个场景:
对接过飞书开发的同学都知道,调用大部分飞书接口之前都要先获取 token 这必然会降低我们自己接口的响应速度。
我们都知道 token 是有过期时间的,这正对应 Redis 的 setex
,所以解决方案如下:
伪代码如下:
public String getToken() {
// 先从redis取
Object redisToken = redisService.getCacheObject(TOKEN_KEY);
if (ObjectUtil.isNotEmpty(redisToken)) {
return redisToken.toString();
}
// 调用飞书,省略部分代码
String response = HttpRequest.post(appConfig.getTokenUrl())
.header(headers)
.body(param.toJSONString())
.execute()
.body();
JSONObject data = JSONObject.parseObject(response);
String token = data.getString("tenant_access_token");
// 存入redis,防止二次获取,提高响应时间。
redisService.setCacheObject("message-set-token", token, data.getLong("expire"), TimeUnit.SECONDS);
return token;
}
同样的,用户的登录的 token 也可以如此处理,不过要搭建高可用的 Redis 集群,防止服务不可用导致全部用户登录失效。
前面提到过自增操作,这用来统计阅读量再合适不过,广义来说就是作为计数器。
伪代码如下:
public void likeArticle(String articleId) {
Long increment = redisTemplate.opsForValue().increment(CACHE_ARTICLE + articleId,1);
log.info("----------increment:{}",increment);
}
点击一次加一,同时返回当前阅读量。
大名鼎鼎的分布式锁其实就是利用setnx
+过期时间实现,这部分会在后面详细讲解。
学完本章,希望大家马上就在开发中用上 Redis ,已经用的思考一下在高并发下会不会有问题。
精雕细刻出佳品,千修百改出华章。好的架构不是设计出来,而是演变出来的。
下一篇聊聊 string 的源码实现——简单动态字符串。