Redis String类型应用场景
Redis作为一个KV数据库服务,其中K(Key)一般都是String类型,V(Value)有很多类型,如:
- String
- Hash哈希表
- List列表
- Set集合(分无序和有序)
基本操作
对于一个K-V类数据库,常用的操作有GET,SET,DELETE,EXIST等
String类型
常用的操作是
Set
127.0.0.1:6379> set hello 1
OK
Get
127.0.0.1:6379> get hello
"1"
但是这样操作数据是永久保存的(正常情况下不会消失)
可以用TTL命令查看key的到期时间
127.0.0.1:6379> ttl hello
(integer) -1
这里返回-1就表示key永远不会过期;
也可以给key设置一个到期时长,使用EXPIRE命令
127.0.0.1:6379> expire hello 10
(integer) 1
返回1表示成功
然后再查看TTL 可以看到key的剩余到期时间
127.0.0.1:6379> ttl hello
(integer) 8
如果key已经过期了 使用ttl会返回-2,表示key不存在
127.0.0.1:6379> ttl hello
(integer) -2
这个时候再使用GET 返回nil,表示key确实已经不存在了
127.0.0.1:6379> get hello
(nil)
有些时候我们需要在set的同时并设置过期时间,这样可以作为一个原子操作,可以使用setex
127.0.0.1:6379> setex hello 10 1
OK
127.0.0.1:6379> ttl hello
(integer) 8
或者
127.0.0.1:6379> set hello 10 EX 1
OK
127.0.0.1:6379> ttl hello
(integer) 8
实际应用场景
1.热销商品信息的缓存
需要展示的商品信息序列化后以string的方式存放在redis里。
127.0.0.1:6379> set hot_goods '[{"goods_id":1,"goods_name":"xxx"},{"goods_id":2,"goods_name":"xxx"}]'
OK
查询的时候可以直接查redis然后反序列化。
2.设置一个有到期时间的锁
使用场景分布式锁,设置一个60s到期的key
先检查锁是否存在
127.0.0.1:6379> exists lock
(integer) 0
设置锁
127.0.0.1:6379> setex lock 60 1
OK
中间进行业务逻辑操作
最后删除锁
127.0.0.1:6379> del lock
(integer) 1
这样就保证只能同时有一个任务在进行业务逻辑操作执行,其他操作在exists命令的时候 会返回1 表示lock这个key存在,业务逻辑上就可以进行跳过不处理;
但是这里面还有一个问题,比如有两条同时执行的任务,都同时触发了exists命令,这时都会返回0
那么都会进入setex lock 60 1命令,并且都会返回OK,这样不就不符合设计的预期了。
可以这样改
将setex命令换成
127.0.0.1:6379> set lock 1 EX 10 NX
OK
在lock过期之前再次执行,将返回nil 表示不成功,这样就可以判断已经有其他任务在执行,业务上也进行跳过处理;
127.0.0.1:6379> set lock 1 EX 10 NX
(nil)
EX(expiration)表示设置到期时间,NX表示在key不存在时才set成功,当然还有一个反向的XX表示key存在时才set成功。
3.时间段内限频
场景为1秒内只能处理10个请求,这是一种很常见的接口限频策略。
基于INCR命令 做自增,在不存在key的情况下 会默认创建一个key默认0 并自增+1,返回1
127.0.0.1:6379> incr i
(integer) 1
第二次调用,在原来的key的基础上自增+1 返回2;
127.0.0.1:6379> incr i
(integer) 2
但是这个key没有到期时间,无法满足在指定时间内判断有多少个请求的预期
所以还需要调用expire,设置1s
127.0.0.1:6379> expire i 1
(integer) 1
可以这样写程序逻辑
# 伪代码
maxCount = 10
count = redis.incr("i")
if count == 1 {
// 第一次设置key 添加过期时间
redis.expire("i", 1)
}
// 如果超过最大允许值,返回false
if count > maxCount {
return false
}
return true
以上就是一些常用的使用场景
对于第三个场景,还是会有一种极限情况导致功能出现bug