Redis常用类型及应用场景

主要类型

  • 字符串(strings,bitmaps)
  • 散列(hashes)
  • 列表(lists)
  • 集合(sets)
  • 有序集合(sorted sets)
  • hyperloglogs
  • 发布订阅(pub/sub)
  • 地理空间(geospatial)
  • Stream(5.0版本新增)

关于命令我推荐看这两个:

应用场景

strings

  • 缓存
  • 分布式锁(setnx)
  • 签到统计(setbit)
  • 计数(incr)

hashes

  • 缓存
  • 用户标签

lists

  • 队列

sets

  • 交集并集
  • 数据去重

zset

  • 排行榜
  • 延时任务
  • 限流

hyperloglogs

  • uv统计(ip统计)

pub/sub

  • 发布订阅(不是特别可靠)

geospatial

  • 附近的人

Stream

  • 队列
  • 发布订阅

其他

利用事务实现秒杀

以php代码为例:

WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,所以在MULTI命令后可以修改WATCH监控的键值)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 库存为5
//实例化redis
$redis = new Redis();
//连接
$redis->connect('127.0.0.1', 6379);
$key = 'sale';
$redis->setnx($key, 0); // 此项不预定义亦可,保证key唯一就行
$redis->watch($key); //监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

$sale_num = $redis->get($key);
if ($sale_num > 4) {
exit();
}

$redis->multi(); //标记事务

$redis->incr($key); //销量+1
sleep(1); //模拟真实环境
$ret = $redis->exec(); // 事务块内所有命令的返回值,按命令执行的先后顺序排列。
if ($ret) {
// 自定义的一个基于medoo的dbclass
include 'db.php';
$db = new db([
'database_type' => 'mysql',
'database_name' => 'test',
'server' => '13sai',
'username' => '13sai',
'password' => '*',
'charset' => 'utf8'
]);
$db->update('goods', ["stock_num[-]" => 1], ['id' => 1]);
}

布隆过滤器

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。

bloom

php实现推荐看看这篇文章:

当然,Redis自己也有第三方模块:

1
2
3
4
5
6
git clone https://github.com/RedisBloom/RedisBloom.git
cd redisbloom
make


/path/to/redis-server --loadmodule ./redisbloom.so

Bloom:向过滤器添加新项,如果尚不存在,则会为您创建一个新的过滤器

1
2
127.0.0.1:6379> BF.ADD newFilter foo
(integer) 1

Bloom:检查过滤器中是否存在项

1
2
3
4
5
127.0.0.1:6379> BF.EXISTS newFilter foo
(integer) 1

127.0.0.1:6379> BF.EXISTS newFilter notpresent
(integer) 0

限流Redis-cell

1
2
3
4
5
6
// 提前安装rust哟
git clone https://github.com/brandur/redis-cell.git
cd redis-cell
cargo build --release
cp target/release/libredis_cell.dylib /path/to/modules/
redis-server --loadmodule /path/to/modules/libredis_cell.so

该模块只有1条指令cl.throttle,它的参数和返回值都略显复杂,接下来让我们来看看这个指令具体该如何使用。

1
2
3
4
5
6
> cl.throttle limitThrot  15  30  60  1
▲ ▲ ▲ ▲ ▲
| | | | └───── need 1 quota (可选参数,默认值也是1)
| | └──┴─────── 30 operations / 60 seconds 这是漏水速率
| └───────────── 15 capacity 这是漏斗容量
> └─────────────────── key

上面这个指令的意思是允许频率为每 60s 最多 30 次(漏水速率),漏斗的初始容量为 15,也就是说一开始可以取 15 个,然后才开始受漏水速率的影响。我们看到这个指令中漏水速率变成了 2 个参数,替代了之前的单个浮点数。用两个参数相除的结果来表达漏水速率相对单个浮点数要更加直观一些。

1
2
3
4
5
6
> cl.throttle limitThrot 15 30 60 1
1) (integer) 0 # 0 表示允许,1表示拒绝
2) (integer) 15 # 漏斗容量capacity
3) (integer) 14 # 漏斗剩余空间left_quota
4) (integer) -1 # 如果拒绝了,需要多长时间后再试(漏斗有空间了,单位秒)
5) (integer) 2 # 多长时间后,漏斗完全空出来(left_quota==capacity,单位秒)

基本上常见的场景就是这些了,各位周末愉快!