Keys:
redis 的 key 是 二进制安全的,可以使用任何二进制串作为key ,空字符串也可以作为key。
1,太长的key 并不是一个好主意,不仅是因为占用更多的内存空间,也是因为查找太长的key可能花费更大的代价。如果需要使用一个很大的值作为key ,可以对它进行hash处理,有利于内存和带宽
2,非常小的key往往也不是一个好主意,尽管小key占用更少的内存但可读性更差。
3,尝试key使用固定格式的语法 ,如: “object-type:id” ,eg:“user:1000:followers" 比 ”u1000flw" 更适合作为key。
4,key允许的最大的大小是512M
不同类型的Key:
String:
> set mykey somevalue
OK
> get mykey
"somevalue"
set 给key 赋值 ,如果 key 已经关联了Value 则会被替换 。Value可以是任何类型的字符 串(包括二进制的数据),比如Value 可以是一张图片的二进制数据,或者是html 。Value 不能超过512MB。
set命令有额外的有趣的参数,如当key已经存在时让set命令返回fail ,或者相反只有key已经存在时set明亮才能成功。
> set mykey newval nx
(nil)
> set mykey newval xx
OK
incr 与 incrby 命令
> set counter 100
OK
> incr counter
(integer) 101
> incr counter
(integer) 102
> incrby counter 50
(integer) 152
类似的命令还有decr 和 decrby ,这些命令将String 转为 Integer 增加1后再设置为新的值,
incr命令的操作是原子性的,两个客户端incr 同一个key ,结果总是加2 的。由于redis是单线程读写,一个客户端在读写时另一个客户端不能执行命令。
getset 命令
给key赋值一个新值并返回旧值。
mset 与 mget 命令
一个命令给多个key赋值
> mset a 10 b 20 c 30
OK
> mget a b c
1) "10"
2) "20"
3) "30"
exists 与 del 命令
exists key ,key存在返回1 ,不存在返回0;del命令删除key返回1,没有删除返回0。
type 命令 ,返回key存储的值的类型
> set mykey x
OK
> exists mykey
(integer)1
> type mykey
string
> del mykey
(integer) 1
> type mykey
none
key 过期
key可以设置一个过期时间,也被较为存活时间 time to live (ttl),当时间流逝,key会被自动销毁。 过期时间可以使用秒或毫秒,key过期的时间可以被持久化在磁盘上,当redis服务停止后,过期时间也会流逝,这意味这redis会保存key过期的日期。
> set key some-value
OK
> expire key 5
(integer) 1
> get key (immediately)
"some-value"
> get key (after some time)
(nil)
>
> set key 100 ex 10
OK
> ttl key
(integer) 9
String 类型 key 的完整命令行:Commands | Redis
List
list 可以用来实现队列和栈的效果
先进先出 --队列
> LPUSH work:queue:ids 101
(integer) 1
> LPUSH work:queue:ids 237
(integer) 2
> RPOP work:queue:ids
"101"
> RPOP work:queue:ids
"237"
先进后出--栈
> LPUSH work:queue:ids 101
(integer) 1
> LPUSH work:queue:ids 237
(integer) 2
> LPOP work:queue:ids
"237"
> LPOP work:queue:ids
"101"
LLen 返回list里元素的个数,key不存在返回0
LMov 将一个list的元素移动到另一个list
> LPUSH board:todo:ids 101
(integer) 1
> LPUSH board:todo:ids 273
(integer) 2
> LMOVE board:todo:ids board:in-progress:ids LEFT LEFT
"273"
> LRANGE board:todo:ids 0 -1
1) "101"
> LRANGE board:in-progress:ids 0 -1
1) "273"
LTrim start end 截取list
list的最大元素个数是 2的32次方 -1 .
Set
redis set 是一个无序的集合,存储独一无二的成员。可以用来存储唯一的元素(eg:访问过某个博客的ip地址),可以用来表示关系(eg:某个角色下的所有用户),可以用来取交集并集差集。
- SADD adds a new member to a set.
- SREM removes the specified member from the set.
- SISMEMBER tests a string for set membership.
- SINTER returns the set of members that two or more sets have in common (i.e., the intersection).
- SCARD returns the size (a.k.a. cardinality) of a set.
> SADD user:123:favorites 347
(integer) 1
> SADD user:123:favorites 561
(integer) 1
> SADD user:123:favorites 742
(integer) 1
> SADD user:456:favorites 561
(integer) 1
> SISMEMBER user:123:favorites 742
(integer) 1
> SISMEMBER user:123:favorites 299
(integer) 0
set的最大成员数量是2的32次方-1.
性能表现:
添加,删除,检查是否存在都是O(1)的操作,这意味这set非常高效,但是当set的成员数量非常多时,需要小心使用 SMembers 命令,这个命令会返回set中的所有元素,复杂度为O(n),可以考虑SScan迭代地取到所有成员。
Hash
hash的数据结构是 键值对的集合,可以用hash表示一个对象,
- HSET sets the value of one or more fields on a hash.
- HGET returns the value at a given field.
- HMGET returns the values at one or more given fields.
- HINCRBY increments the value at a given field by the integer provided.
- HKEYS, 所有的field
- HVALS, 所有的value
- HGETALL ,所有的field-value
大部分Hash 命令时间复杂度是O(1),HKEYS,HVALS,HGETALL 是O(n)
每一个hash可以存储2的32次方-1 个 键值对。
> HSET user:123 username martina firstName Martina lastName Elisa country GB
(integer) 4
> HGET user:123 username
"martina"
> HGETALL user:123
1) "username"
2) "martina"
3) "firstName"
4) "Martina"
5) "lastName"
6) "Elisa"
7) "country"
8) "GB"
ZSet
Sorted Set ,存储独一无二的元素,并通过score 排序,多个元素有相同的score时,通过元素的字典排序。可以用于:
1,排行耪,获取score最高的list
2,限速器,用Sorted Set 实现滑动窗口速率限制器,限制api请求速率
示例:向排行榜中添加用户
> ZADD leaderboard:455 100 user:1
(integer) 1
> ZADD leaderboard:455 75 user:2
(integer) 1
> ZADD leaderboard:455 101 user:3
(integer) 1
> ZADD leaderboard:455 15 user:4
(integer) 1
> ZADD leaderboard:455 275 user:2
(integer) 0
获取榜单前3名
> ZRANGE leaderboard:455 0 2 REV WITHSCORES
1) "user:2"
2) "275"
3) "user:3"
4) "101"
5) "user:1"
6) "100"
获取某一用户的排名
> ZREVRANK leaderboard:455 user:2
(integer) 0
基本命令
Stream
没看懂,不写
geospatial
地理位置,存储地点和它的经纬度
示例:存储充电站点的位置
> GEOADD locations:ca -122.27652 37.805186 station:1
(integer) 1
> GEOADD locations:ca -122.2674626 37.8062344 station:2
(integer) 1
> GEOADD locations:ca -122.2469854 37.8104049 station:3
(integer) 1
获取指定位置周围5km内的站点,和直线距离
> GEOSEARCH locations:ca FROMLONLAT -122.2612767 37.7936847 BYRADIUS 5 km WITHDIST
1) 1) "station:1"
2) "1.8523"
2) 1) "station:2"
2) "1.4979"
3) 1) "station:3"
2) "2.2441"
HyperLogLog
基数
添加元素
> PFADD members 123
(integer) 1
> PFADD members 500
(integer) 1
> PFADD members 12
(integer) 1
基数数量
> PFCOUNT members
(integer) 3
bitmap
位图,每一位可以表示某个状态
示例:有一千位员工,记录员工2023-06-27 这一天的出勤状态,
记录员工123的出勤状态
> SETBIT pings:2023-06-27 123 1
(integer) 0
获取员工123在2023-10-13 这一天的出勤状态
> GETBIT pings:2023-10-13 123
1
Bitfield
记录元素的多个数字型状态,可以对这些状态的值进行 set ,get ,incrby 操作,且操作是原子性的。
示例:
假设你是一个游戏的设计者,你想要记录每一位玩家的两个状态:拥有的金币数和击杀的怪物数 。你可以使用bitfield
玩家cool_hansonh 注册了游戏,初始金币设为1000
> BITFIELD player:cool_hansonh:stats SET u32 #0 1000
1) (integer) 0
u32 : 表示用32 bit 存储数据
#0 :表示偏移量是0
cool_hansonh 击杀了哥布林拯救了公主hannah,获取了50金币
> BITFIELD player:cool_hansonh:stats INCRBY u32 #0 50 INCRBY u32 #1 1
1) (integer) 1050
2) (integer) 1
第一个32位表示金币数,第二个32位表示击杀怪物数
cool_hansonh 在铁匠铺花了999金币购买了英雄武器:猎杀游魂大剑
> BITFIELD player:cool_hansonh:stats INCRBY u32 #0 -999
1) (integer) 51
获取 cool_hansonh 的金币数和怪物击杀数
> BITFIELD player:1:stats GET u32 #0 GET u32 #1
1) (integer) 51
2) (integer) 1