Redis基本使用
Nevermore 2024-03-11 DataBase
- 连接远程服务
redis-cli -h 127.0.0.1 -p 6379
1
- 普通命令
set key value
set key value [expiration EX seconds | PX miliseconds]
set key 1 ex 10
1
2
3
2
3
# 符号匹配
- ?:匹配一个字符
- *:匹配0个或多个字符
- [abc] :只能匹配a b c 中的字符
- [a-c] : 匹配a到c的字符,包含边界
- [^a] : 排除字符a
127.0.0.1:6379> keys w* # 禁止使用- O(N),redis只有一个线程处理请求,若key很多会发生阻塞
1) "wang"
1
2
2
# 键相关
exists key1 [key2, key3...] : 返回key存在的个数, hash_ O(1)。一个命令对应一个网络请求,所以尽量将多个请求一次发送。
del key1 [key2, key3...] : 删除一个(若干个)键
expire key seconds: 给key设置过期时间 (pexpire key 毫秒),成功返回1,失败返回0.必须针对存在的key
ttl(pttl) key:查询过期时间,-1表示没有关联过去,-2表示key不存在,正常返回剩余的过期时间
- 定期删除:抽取一部分,过期删除
- 惰性删除:已经过期但未删除,当访问时再删除。
实现基于优先级队列的定时器删除:元素=时间戳+过期时间,队首元素为最早过期的,检测到过期就删除。
#include <chrono>
#include <iostream>
#include <queue>
#include <vector>
#include <thread>
int64_t getTimestamp() { //milliseconds
auto now = std::chrono::system_clock::now();
return std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
}
void insert(std::priority_queue<int64_t, std::vector<int64_t>, std::greater<int64_t>>& minHeap, int64_t expireIn) {
int64_t ExpEndTime = getTimestamp() + expireIn;
minHeap.push(ExpEndTime); // 让结束时间最小的点在堆顶,会首先释放
}
int main() {
std::priority_queue<int64_t, std::vector<int64_t>, std::greater<int64_t>> minHeap;
std::vector<int64_t> expTime{1,2,3,4,5};
for(const auto t : expTime) {
insert(minHeap, t);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
while(!minHeap.empty()) {
int64_t tp = minHeap.top();
minHeap.pop();
std::cout << "The latest end time is:" << tp << std::endl;
}
return 0;
}
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
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
# 类型
- redis 的key都是string类型,但是value可能存在多种类型(none, string, list, set, zset(有序集合), hash, stream),使用type查看。O(1da)
127.0.0.1:6379> lpush key1 1 2 3
(integer) 3
127.0.0.1:6379> type key1
list
127.0.0.1:6379> sadd key2 1 2 3
(integer) 3
127.0.0.1:6379> type key2
set
127.0.0.1:6379> type key3
none
127.0.0.1:6379> hset key3 f v
(integer) 1
127.0.0.1:6379> type key3
hash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
数据类型 | 内部编码 | 解释 |
---|---|---|
string | raw | =c/c++ char |
int | 整数longlong | |
embstr | 优化短字符串 | |
hash | hashtable | 哈希表 |
ziplist | 压缩链表 | |
list | linkedlist | 链表/quicklist = linkedlist + ziplist |
ziplist | - | |
set | hashtable | - |
intset | 整数 | |
zset | skiplist | 跳表 |
ziplist | - |
- object encoding key - 查看数据类型中的内部编码
# 基本操作
操作名称 | 运行指令 | 举例 | 解释 |
---|---|---|---|
插入SET | set key value [expiration EX seconds PX | milliseconds] [NX | XX] | set k 10 ex 20 nx | EX/PX:设置超时 NX:不存在创建,存在不设置返回Nil XX:存在跟新key的val,不存在不设置返回Nil 对应的选项可对应命令SETNX/SETPX/SETEX |
flushall | 清空数据库 | ||
GET | get key | 获取value,只支持string,若是其他类型会出错 | |
MSET/MGET | mgetg key [key1...] mset key1 value1 [key2 value2...] | 一次操作多个Key,减少网络请求次数。 | |
incr / incrby | incr key / incrby key 10 | value必须是整数,value + 1 / value + n;可以对不存在的key操作,相当于原来为0。(可以使用正负数,负数与decr类似) | |
decr / decrby | value - 1 / value - n | ||
incrbyfloat | value +/1 小数 (只有加负数实现减法) |
# 字符串操作
操作名称 | 运行指令 | 举例 | 解释 |
---|---|---|---|
字符串 | |||
append | append key value | 只针对value为string类型,将新的string添加到后面,key不存在则创建。返回字符总长度 | |
GETRANGE | getrange key start end | getrange li 0 -1 | 获取key对应的字符串,start和end之间的字符(左闭右闭)-1代表倒数第一个字符 |
SETRANGE | setrange key offset value | 从第offset位置开始替换,为value | |
STRLEN | strlen key | 计算value长度 |
- 中文字符串输入为utf8,则存储也为utf8,使用--raw可查看
127.0.0.1:6379> append key5 你好
(integer) 6
127.0.0.1:6379> keys key5
1) "key5"
127.0.0.1:6379> get key5
"\xe4\xbd\xa0\xe5\xa5\xbd"
ubuntu@VM-4-13-ubuntu:~/qemu-5.1.0$ redis-cli --raw
127.0.0.1:6379> get key5
你好
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 应用场景
- 作为缓存,应用先查询redis,存在则返回;不存在则查询Mysql,同时将数据写入redis。(给key设置过期时间,防止数据过多;内存不足redis利用内部的淘汰策略)。redis不能分表,对应不同的业务使用不同的key命名方式:业务名:对象名:唯一标识:属性。
- 计数功能,如访问量。如key为(资源名称:资源号)value为次数。采用异步方式将数据同步到mysql,如果要统计topk,可以请求mysql。(面临的问题:防作弊、避免单点、数据持久化)
- 共享Session会话。负载均衡的主机可以共同访问。
- 手机验证码。防止用户申请过多sms,设置key过期时间如30秒,如果redis存在key则禁止申请。
# 哈希
- field 是不能重复的
操作名称 | 运行指令 | 举例 | 解释 |
---|---|---|---|
HSET | hset key field1 value1 [field2 value2...] | 设置hash | |
HGET | hget key filed | 获得key中field对应的value | |
HEXISTS | hexists key filed | 判断hash中是否有指定的字段O(1); 1表示存在,0表示不存在 | |
HDEL | hdel key filed [filed...] | 删除filed和对应的value | |
*HKEYS | hkeys key | 获取hash中的所有字段field.存在风险 | |
*HVALS | hvals key | 获取所有的value | |
*HGETALL | hgetall key | field:value | |
HMGET | hmget key f1 [f2 f3...] | 查询多个字段的value | |
*
不建议使用
- 应用场景
- 存储用户信息,string + Json也可以
# 链表
- 列表中的元素是可以重复的
- 类似于双向链表,可以当成(队列/栈)使用

操作名称 | 运行指令 | 举例 | 解释 |
---|---|---|---|
LPUSHX | lpushx key element [element1, ...] | key存在,将一个/多个从左边插入;若key不存在是直接返回 | |
LINDEX | lindex key -1 | O(链表长度) | |
LINSERT | linsert key <before | after> pivot element | 先从左边开始找到值为pivot的位置,然后插入element | |
LREM | lrem key count element | count > 0从左往右删除count个的element count = 0:删除所有 count < 0: 从右往左删 | |
LTRIM | ltrim key start stop | 保留start和stop之间的元素(两边的元素都被删除了) | |
LSET | lset key index element | 修改指定位置的元素(超出范围报错) | |
blpop/brpop | blpop key [key...] timeout | b=block,阻塞删除,可以设置阻塞时间(处理过的阻塞,不会对redis产生负面影响)。可以指定多个key。若列表为空,则不立即返回,在超时时间内有元素插入则立即返回这个插入的元素 |
新版本(6.2)的lpop和rpop新增了count参数,代表删除元素的个数:lpop key [count]
redis6 blpop的timeout允许为小数,单位为秒
应用场景
- 队列的性质:生产者消费者模型lpush + brpop:谁先执行brpop谁就抢先拿到了元素
- 同侧存取为栈,异侧存取为队列
- 用hash中field和value,所有field的存到list,value对应内容
# 集合
- 元素是无序的
操作名称 | 运行指令 | 解释 |
---|---|---|
SADD | sadd key member [member,...] | 添加集合一个/多个元素(不能重复,自动去重) |
SMEMBERS | smembers key | 获取所有元素O(1) |
SISMEMBER | sismember key number | 判断当前元素是否在集合中 |
SPOP | spop key [count] | 随机删除末尾count个元素(通过生成随机数来删除) |
SRANDMEMBER | SRANDMEMBER key | 随机获取,不删除 |
SMOVE | smove source destination member | 把member从集合source删除,添加到集合destination中 |
SREM | srem key member [member] | 删除一个/多个member |
SINTER | sinter key [key...] | key对应一个集合,返回交集,O(N*M;最小个数X最大个数) |
SINTERSTORE | sinterstore destination key [key...] | 将交集存储到destination |
SUNION | sunion key [key...] | 求并集 |
SDIFF | sdiff key [key...] | 差集 |
SCARD | scard key | 求元素个数O(1) |
- 应用场景
- 计算两个用户共同的数据
- 数据去重
# 有序集合
- 按照分数(浮点)进行排序,每个member都有一个分数
- member是唯一的,但是分数可以重复。
- 分数相同,按元素字典序排列;否则按照分数排列。默认升序排列

操作名称 | 运行指令 | 解释 |
---|---|---|
ZADD | zadd key [nx | xx] [GT | LT] [CH] [INCR] score member [score member...] | XX:只更新存在的element;NX:只更新新加入的element。 GT:greater than,只更新比存在元素大的,否则不添加;LT:less than CH:普通清空返回值为添加的个数,加了ch还会返回修改的个数 incr :like zincrby |
ZRANGE/ZRANGEBYSCORE | zrange key start stop [withscores] | 查看下标范围内的所有element, O(logN + M)/ 查看分数区间内 |
ZCARD | zcard key | O(1)获取元素个数 |
ZCOUNT | zcount key min max | 默认闭区间,返回分数在区间内的元素个数;若使用开区间可以写成,zcount key (1 (3,加 '('. O(logN) , 另表示无穷的写法:zcount key -inf inf |
ZREVRANGE | zrevrange key start stop | 逆序 |
ZPOPMAX | zpomax key [count] | 删除分数最大的count个元素 |
BZPOPMAX | bzpopmax key [key...] timeout | 从多个key中只选一个删除一次,阻塞删除分数最大的,集合为空发生阻塞,最多阻塞时间为timeout。 |
ZPOPMIN / BZPOPMIN | ||
ZRANK | zrank key member | 查看某个member的序号O(logN), 升序, 首元素下标为0 |
ZREVRANK | 降序 | |
ZSCORE | zscore key member | 返回指定元素的分数O(1) |
ZREM | zrem key member [member...] | 删除一个key中的一个/多个member |
ZREMRANGEBYRANK | zremrangebyrank key start stop | 删除小标范围内的数据 |
ZINCRBY | zincrby key increment member | 给key中的member分数加上increment。支持浮点数 |
ZINTERSTORE | zinterstore destination numkeys key [key...] [WEIGHTS weight [weight...]] [Aggregate < SUM | MIN | MAX>] | 求numkeys个的交集,并把结果存到key为destination中,权值weight代表每个集合的重要程度,结果scores * weight 如果不同的key中,元素相同但是分数不同,则保存的结果根据Aggregate来对分数进行标定。 |
ZUNIONSTORE | ... | 求并集 |
- 应用场景
- 排行榜
# 其他
- 渐进式查询
如果一次获取很多的数据如key * 会造成单线程的数据库卡住。通过渐进式遍历可以解决这个问题。
每次不是拿到所有的key,而是多次遍历,多次查询。
操作名称 | 运行指令 | 解释 |
---|---|---|
scan | scan cursor [MATCH pattern] [count n] [TYPE type] | 从下标为cursor的位置开始(如0),查询n个,返回结果为下一个位置的下标。当返回为0,代表遍历结束 cursor不一定连续,只有redis自己可以识别,客户端使用就可以了 pattern : 参考符号匹配 count 是个建议的个数,默认是10,返回也许和设置不一定相同 type:指定key类型list、hash... |
如果在遍历期间键发生修改,会导致遍历重复或遗漏。
- redis默认使用0号数据库,而redis提供了编号为0-15的数据库
select dbnumb(【0-15】)
dbsize # 数据库的大小
1
2
2
flushdb # 删除当前数据库的所有key
flushall # 删除所有的key
1
2
2