第一章 STRING
string(字符串)简介
- 所有key都是字符串类型。其他类型都是在字符串类型基础上建立的。
- 字符串类型的值,可以是简单的字符串或json,xml。可以是数字(整数,浮点,内部会转换),可以是二进制(图片,音频,视频)
- 最大值不能超过512MB,一般建议在100k下。并发和流量更好。
- 适用于缓存,计数器和分布式锁
内部编码 字符串类型的内部编码有3种,Redis会根据当前值的类型和长度决定使用哪种内部编码实现。
- int:8个字节的长整型。
- embstr:小于等于39个字节的字符串。
- raw:大于39个字节的字符串。
命令
设置
set key value [ex seconds] [px milliseconds] [nx|xx]
ex 秒级过期时间。px 毫秒级过期时间。 nx不存在成功用于添加。xx必须存在才成功用于更新。
set key value 设置key value,无论key是否存在都设置。
setnx key value 设置key value,key不存在才设置。用于插入。
set key value xx 设置key value,key存在才设置。用于更新(set a hello xx)。如果不存在返回nil。无法更新。
redis由于是单线程,多个客户端执行setnx 只有一个客户端可以成功。可以作为分布式锁的一种实现方案。
http://redis.io/topics/distlock。官方实现分布锁的指南。
获取和删除
get key 获取对应的value,不存在返回nil。时间复杂度
del key 删除key-value,成功返回1,不成功不存在返回0。时间复杂度
自增自减
incr key key自增1,如果key不存在,自增后get(key)=1
值不是整数,浮点数也不可以。返回错误。
值是整数,返回自增后结果。
值不存在,按照值为0自增。返回结果1
decr key key自减1,如果key不存在,自减后get(key)=-1
incrby key k key自增k,如果key不存在,自增后get(key)=k
decrby key k key自减k,如果key不存在,自减后get(key)=-k
举例:
set/get
127.0.0.1:6379> set hello world //hello为key值,world为value值
OK
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> set hello updatehello //更新hello
OK
127.0.0.1:6379> get hello
"updatehello"
setnx
127.0.0.1:6379> setnx hello inserthello //hello存在
(integer) 0
127.0.0.1:6379> setnx hello2 inserthello //hello2不存在
(integer) 1
del
127.0.0.1:6379> del hello
(integer) 1
127.0.0.1:6379> get hello
(nil)
incr/decr 自增自减1
127.0.0.1:6379> set number 100
OK
127.0.0.1:6379> incr number
(integer) 101
127.0.0.1:6379> get number
"101"
127.0.0.1:6379> incr number2 //number2不存在
(integer) 1
127.0.0.1:6379> get number2
"1"
127.0.0.1:6379> decr number
(integer) 100
127.0.0.1:6379> decr number2
(integer) 0
127.0.0.1:6379> decr number2
(integer) -1
127.0.0.1:6379> get number
"100"
127.0.0.1:6379> get number2
"-1"
incrby/decrby
127.0.0.1:6379> incrby number 10
(integer) 110
127.0.0.1:6379> get number
"110"
127.0.0.1:6379> incrby number3 10 //number3不存在
(integer) 10
127.0.0.1:6379> get number3
"10"
127.0.0.1:6379> decrby number2 10
(integer) -11
127.0.0.1:6379> decrby number4 10 //number4不存在
(integer) -10
127.0.0.1:6379> get number2
"-11"
127.0.0.1:6379> get number4
"-10"
- 批量设置
n次get=n次网络时间+n次命令时间,如果要一次获取10万个key,应该批量来一次来1000这样。
一次mget
nget=n次网络时间+n次命令时间,如果要一次获取10万个key,应该批量来一次来1000这样。
mget key1 key2 key3 批量获取key 1次网络时间+n次命令时间,存在返回,不存在返回nil。按照传入键的顺序返回。
mset key1 value1 key2 value2 key3 value3
批量设置可以提高效率。没有mget只能一条一条执行命令,一条一条返回结果。
mget 将命令为一条命令发送。执行n条命令后。在作为一个结果返回所有的值。
假设网络为1毫秒,命令为0.1毫秒。1000次命令。。。1000次get需要1100毫秒。。而1次mget需要101毫秒。
每次发送的命令数应该控制。过多会阻塞redis或网络拥塞。
例子:
127.0.0.1:6379> mset k1 1 k2 2 k3 3 k4 4 k5 5
OK
127.0.0.1:6379> mget k1 k2 k3 k4 k5
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
- 不常用命令
getset key newvalue 设置新value并返回旧的value
append key value想字符串尾部追加新值。
strlen key 返回字符串长度,中文utf8占用2个字节。英文1个字节。
incrbyfloat key 增加key对应的值,float带小数点。
getrange key start end 获取指定位置的部分字符串。
setrange key index value 设置指定位置的字符。
127.0.0.1:6379> getset k1 01 //k1 原值为1
"1"
127.0.0.1:6379> get k1
"01"
127.0.0.1:6379> append k1 0001 //追加0001
(integer) 6
127.0.0.1:6379> get k1
"010001"
127.0.0.1:6379> strlen k1 //查看k1长度
(integer) 6
127.0.0.1:6379> set k2 1
OK
127.0.0.1:6379> get k2
"1"
127.0.0.1:6379> incrbyfloat k2 1.23 //增加1.23
"2.23"
127.0.0.1:6379> get k2
"2.23"
127.0.0.1:6379> getrange k1 2 4
"101"
127.0.0.1:6379> setrange k1 2 4 //按照下标设置新值,下标为2的设置为4
(integer) 23
127.0.0.1:6379> get k1
"10401.09999999999999964"
- 执行命令的时间复杂度 |命令|时间复杂度| |----|---------| |set key| O(1)| |get key| O(1)| |del key| O(k),k是键的个数。| |mset key value| O(k),k是键的个数。| |mget key| O(k),k是键的个数。| |incr key| O(1)| |decr key| O(1)| |incrby key increment| O(1)| |decrby key decrement| O(1)| |incrbyfloat key increment| O(1)| |append key value| O(1)| |strlen key| O(1)| |setrange key offset value| O(1)| |getrange key start endo(n)|n为字符串长度。获取字符串很快,如果字符串不长,视为O(1)|
典型应用场景
- 缓存功能
1.用户访问web服务来获取数据。redis作为缓存层,MySQL作为存储层。
绝大部分请求的数据都是从redis中获取。redis快速高并发,可以加速读写和降低后端压力作用。
2.当Redis+MySQL同时使用。获取数据的流程(接口和程序都有这样的逻辑)
user->访问server获取数据,首先会在redis中获取,如果存在直接返回给用户。
3.如果redis获取不到数据,则访问mysql数据,有结果则将结果写回导redis中并设置一个过期时间。
再返回给用户。如果mysql也没有数据则直接返回。
如何保持数据的一致性。
以下内容转载信息如下。版权归作者所有。
作者:大宽宽
链接:https://www.zhihu.com/question/319817091/answer/653985863
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
不一致是指:
用户同时访问redis和底层db(比如mysql),存在一段时间内数据不一致的情况。redis不存自动同步Mysql的更新。需要一种机制更新数据到redis
1. Redis里的数据不立刻更新,等redis里数据自然过期。然后去DB里取,顺带重新set redis并设置过期时间。
好处是代码比较简单,坏处是会有一段时间DB和Redis里的数据不一致。
这个不一致的时间取决于redis里数据设定的有效期,比如10min。但如果Redis里数据没设置有效期,这招就不灵了。
2. 更新DB时总是不直接触碰DB,而是通过代码。而代码做的显式更新DB,然后马上del掉redis里的数据。
在下次取数据时,模式就恢复到了上一条说的方式。这也算是一种Cache Aside的变体。
这要做的好处是,数据的一致性会比较好,数据不一致的时间会在1s以下,对于绝大部分的场景是足够了。
但是有极少几率,由于更新时序,下Redis数据会和DB不一致。
1有更新不及时的问题,2有极端情况下数据会不一致的问题。
所以常规Cache代码会把1+2组合起来,要求Redis里的数据必须有过期时间,并且不能太长。
同时如果是主动对数据进行更新,Cache的数据更新也会比较及时。并且2并不一定总是行得通。
比如OLTP的服务在前面是Cache+DB的模式,而数据是由后台管理系统来更新的,总是不会触碰OLTP服务,更不会动Cache。
这时将Redis看作是存储也算是一种方案。就是:
3. Redis里的数据总是不过期,但是有个背景更新任务(“定时执行的代码” 或者 “被队列驱动的代码)读取db,把最新的数据塞给Redis。这种做法将Redis看作是“存储”。访问者不知道背后的实际数据源,只知道Redis是唯一可以取的数据的地方。
当实际数据源更新时,背景更新任务来将数据更新到Redis。这时还是会存在Redis和实际数据源不一致的问题。如果是定时任务,最长的不一致时长就是更新任务的执行间隔;如果是用类似于队列的方式来更新,那么不一致时间取决于队列产生和消费的延迟。
常用的队列(或等价物)有Redis(怎么还是Redis),Kafka,AMQ,RMQ,binglog,log文件,阿里的canal等
这种做法还有一种变体Write Through,写入时直接写DB,DB把数据更新Cache,而读取时读Cache。
Write Through + Cache当存储
以上方式无论如何都会有一段时间Redis和DB会不一致。
实践上,这个不一致时间短则几十ms,长可以到几十分钟。这种程度的一致性对于很多业务场景都已经足够了。
用户无法区分自己读取的是Redis还是DB,只能读取到其中的一个。这时数据看起来直觉上是没问题的就可以接受了。
实战 记录网站每个用户个人主页的访问量
incr userid:pageview(单线程:无竞争)
因为userid是一个第一无二的值,单线程无论你并发有多少。也不会记错数和有竞争。因为是顺序执行的。
缓存视频的基本信息(数据源在mysql中)伪代码
user->访问appserver获取vid(视频id)—>
首先会在redis缓存汇总获取,如果有就返回给用户
不存在就访问mysql。并回写到redis中。再返回用户。
接口和程序会有这样的逻辑。
public VideoInfo_get(long id){
String redisKey = redisPrefix + id;
VideoInfo_videoInfo = redis.get(redisKey); 首先从redis获取。只能取出二进制或者字符串
if (videoInfo == null){
videoInfo = mysql.get(id);如果空,就在mysql中读取。
if(videoInfo !=null){
redis.get(redisKey,serialize(videoInfo)); 如果在mysql中取到了。则写入到redis中
}
}
}
分布式id生成器
多个服务,每次获取的id是自增的。多个应用并发去读取递增。
incr id(原子操作),因为单线程的。不存在重复。一个一个执行。
限速
注册和登录网站时,用户输入验证码。限制每分钟获取验证码的频率。比如一分钟只能获取一次。也可以用在限制ip地址上
phoneNum='138xxxxxxxxxx';
key = 'shortMsg:limit:' + phoneNum;
isExists = redis.set(key,1,"EX 60","NX");
if (isExists != null || redis.incr(key) <= 5){
// 通过
}else{
// 限速
}
还可以用作共享session。可以使用更多场景。发挥想象力就完事了。
第二章 HASH
hash,每一个语言都提供的类型,叫法可能是哈希,字典等等。redis中指键值本身又是一个键值对结构。
例:
key field value
user:1:info name ronaldo
age 40
date 201
key还是一个字符串。可以理解为mysql中的一张表。 field可以理解为一个属性,可以理解为mysql一张表中的字段。每个field不可以相同。但是value可以相同 value可以理解为属性的值,可以理解为mysql一张表中字段的值。
hget key field 获取hash key对应的field的value hset key field value 设置hashkey对应field的value hdel key field 删除hash key 对应filed的value hexists key field 判断field是否存在 hlen key field 获取field的数量
hset/hget 只能设置一个field value值
127.0.0.1:6379> hset user1:info name vip
(integer) 1
127.0.0.1:6379> hget user1:info name
"vip"
hmset/hmget 设置多个filed和value值
127.0.0.1:6379> hmset user2:info name vvip age 100 date today
OK
127.0.0.1:6379> hmget user2:info name age date
1) "vvip"
2) "100"
3) "today"
127.0.0.1:6379> hget user2:info name
"vvip"
127.0.0.1:6379> hget user2:info age
"100"
127.0.0.1:6379> hget user2:info date
"today"
hdel 删除field
127.0.0.1:6379> hdel user2:info date
(integer) 1
127.0.0.1:6379> hmget user2:info name age date
1) "vvip"
2) "100"
3) (nil)
检查field是否存在,存在返回1,不存在返回0
127.0.0.1:6379> hexists user2:info name
(integer) 1
127.0.0.1:6379> hexists user2:info date
(integer) 0
计算key的field数量
127.0.0.1:6379> hlen user2:info
(integer) 2
127.0.0.1:6379> hlen user1:info
(integer) 1
o(n) hmget key field1 field2 ... 批量获取field对应的值 o(n) hmset key field1 value1 field2 value2 .... 批量设置hashkey的一批field value o(n) hgetall key 返回key对应的field和value,小心使用 hvals key 返回key对应所有field的value hkeys key 返回key对应所有的field
127.0.0.1:6379> hgetall user2:info
1) "name"
2) "vvip"
3) "age"
4) "100"
127.0.0.1:6379> hvals user2:info
1) "vvip"
2) "100"
127.0.0.1:6379> hkeys user2:info
1) "name"
2) "age"
127.0.0.1:6379>
hsetnx key field value 设置hashkey对应field的value,如果field存在则失败 hincrby key field intCount 设置对应的field的value自增整数 hincrbyfloat key field floatCount 设置对应field的value自增浮点数
127.0.0.1:6379> hsetnx user2:info name 101
(integer) 0
127.0.0.1:6379> hsetnx user3:info name 101 //user3不存在才会执行。
(integer) 1
127.0.0.1:6379> hincrby user3:info name 100
(integer) 201
127.0.0.1:6379> hincrbyfloat user3:info name 23.45
"224.45"
实战:
1.记录网站每个用户个人主页的访问量
hincrby user:1:info pageview count
2.缓存视频的基本信息(数据源在mysql中)伪代码
String redisKey = redisPrefix + id;
Map<String,String> hashMap = redis.hgetAll(redisKey);
VideoInfo_videoInfo = transferMapToVideo(hashMap);
if (videoInfo == null){
videoInfo = mysql.get(id);
if(videoInfo !=null ){
redis.hmset(redisKey,transferVideoToMap(videoInfo));
}
}
}
基本上跟string的逻辑是一样的。string需要初始化。而哈希使用map转换即可。
string和hash对比
| string与hash对比 | |
|---|---|
| string | get,set,del,incr,incrby,decr,decrby,mset,mget |
| hash | hget,hset,hdel,hincrby,hmset,hmget |
对用户信息更新
第一种包装成一个对象。
key value(serialize:json或xml或protobuf) //包装成一个对象。通过序列化。
user:1 {"id":1,"name":"rold","age":40,"pageview":50000}
set user:1 serialize(userinfo) 如果更新每次都要写这么多。
第二种分开写,不影响单条更新和增加。但是信息不是一个整体。不利于管理。
set user1:age 41
key values
user:1:name world
user:1:age 40
user:1:pageview 500000
第三种使用哈希
key field value
user:1:info name ronaldo
age 40
pageview 5000000
hset user:1:info age 41 直接将年龄更新到41岁
第一种方案,编程简单节约内存,但是序列化开销大,更新属性操作整个数据。先序列化更新后在序列化。
第二种方案,直观并且可以部分更新,但是内存占用比较大,key比较分散不利于管理。
第三种方案,直观节省空间也可以部分更新,但是变成稍微复杂,ttl不好控制。
第三章 LIST
特点是有序,可以重复,左右变量插入弹出 key elements user:1:message a-b-c-d-e-f-g
命令 rpush key value1 value2 ...o(1-n) lpush key value1 value2 ...o(1-n) linsert key before|after value newvalue o(n) 选在在指定值的前|后插入新值 lpop key 从左边删除一个元素 o(1) rpop key 从右边删除一个元素 o(1) lrem key count value o(n) count>0 从左到右删除最多count个value相等的值 正数 count<0 从右到左删除最多count个value相等的值 负数 count=0 删除所有value相等的值 ltrim key start end 列表修剪 o(n) 做大列表删除比较有效。 lrange key start end(包含end) 查询指定范围item o(n) lindex key index 获取指定下标的item o(n) llen key 获取列表长度 lset key index newvalue 指定索引值为新值 o(n)
lpush/rpush 左/右插入新值
127.0.0.1:6379> lpush u:1:a leftinsert
(integer) 2
127.0.0.1:6379> rpush u:1:a rigehtinsert
(integer) 3
llen 计算长度
127.0.0.1:6379> llen u:1:a
(integer) 3
lrange 获取子列表值
127.0.0.1:6379> lrange u:1:a 0 3
1) "leftinsert"
2) "abcdefg"
3) "rigehtinsert"
获取所有值
127.0.0.1:6379> lrange u:1:a 0 -1
1) "leftinsert"
2) "higklmn"
3) "higklmn"
4) "higklmn"
5) "higklmn"
6) "higklmn"
7) "higklmn"
8) "higklmn"
9) "higklmn"
10) "higklmn"
lpop/rpop 左/右弹出值
127.0.0.1:6379> lpop u:1:a
"leftinsert"
127.0.0.1:6379> rpop u:1:a
"rigehtinsert"
lindex 获取指定下标的值
127.0.0.1:6379> lindex u:1:a 2
"rigehtinsert"
127.0.0.1:6379> lindex u:1:a 1
"abcdefg"
lrem 删除指定值的个数。1就是删除一个相等的值
127.0.0.1:6379> lrange u:1:a 0 -1
1) "leftinsert"
2) "higklmn"
3) "higklmn"
4) "higklmn"
5) "higklmn"
6) "higklmn"
7) "higklmn"
8) "higklmn"
9) "higklmn"
10) "higklmn"
127.0.0.1:6379> lrem u:1:a 2 higklmn
(integer) 2
127.0.0.1:6379> lrem u:1:a -2 higklmn
(integer) 2
127.0.0.1:6379> lrem u:1:a 0 higklmn
(integer) 5
127.0.0.1:6379> lrange u:1:a 0 -1
1) "leftinsert"
linsert指定位置插入新值
127.0.0.1:6379> linsert u:1:a after leftinsert abcdefg
(integer) 3
127.0.0.1:6379> lrange u:1:a 0 3
1) "leftinsert"
2) "abcdefg"
3) "rigehtinsert"
ltrim 截取指定范围列表的值
127.0.0.1:6379> ltrim u:1:a 0 1
OK
127.0.0.1:6379> lrange u:1:a 0 1
1) "leftinsert"
2) "abcdefg"
lset 更新指定下标的值为新值
127.0.0.1:6379> lset u:1:a 1 higklmn
OK
127.0.0.1:6379> lrange u:1:a 0 1
1) "leftinsert"
2) "higklmn"
实战:
TimeLine
关注用户在更新的时候。可以看到最新的微博。
里面也用了插入和弹出等等的操作。可以看出像一个列表。
1-2-3-4-5-6-7-8
当你关注的人更新微博lpush 10-1-2-3-4-5-6-7
lrange获取10条微博。再用lset设置内容。再序列化。做一个这样的接口。
blpop key timeout 阻塞弹出。timeout0则不阻塞。
brpop key timeout 阻塞版本,timeout0则不阻塞。
lpush+lpop=stack 栈的功能
lpush+rpop=queue 队列的功能
lpush+ltrim=capped collection 有限列表
lpush+brpop=message queue 消息队列系统。
第四章 SET
set集合
是无序的,不允许有重复元素,支持集合间的api
key values
user:1:follow it musci his sports
S开头
sadd key elements 对key添加elements 如果存在返回0.不报错 o(1)
srem key elements 删除key中的element o(1)
scard key 计算集合中的所有元素个数
sismember key elements 判断元素是否在集合中
srandmember key count 随机挑选count个元素(不会弹出数据),可以随机返回多个元素
spop key 随机弹出一个元素。每次只能弹出一个。5.0也可以弹出多个元素。
smembers key 返回所有的元素,返回无序,小心使用。集合大会阻塞redis。
127.0.0.1:6379> sadd u:1:f it
(integer) 1
127.0.0.1:6379> sadd u:1:f it //不允许有重复的值
(integer) 0
127.0.0.1:6379> sadd u:1:f it sports music movies //增加多个值
(integer) 4
127.0.0.1:6379> scard u:1:f //计算个数
(integer) 4
127.0.0.1:6379> sismember u:1:f it //是否存在
(integer) 1
127.0.0.1:6379> sismember u:1:f musicd
(integer) 0
127.0.0.1:6379> srandmember u:1:f 3 //随机返回多个元素
1) "it"
2) "movies"
3) "music"
127.0.0.1:6379> smembers u:1:f //返回全部元素
1) "movies"
2) "it"
3) "sports"
4) "music"
127.0.0.1:6379> srem u:1:f it //删除一个元素
(integer) 1
127.0.0.1:6379> srem u:1:f ot
(integer) 0
127.0.0.1:6379> spop u:1:f //随机删除一个元素
"music"
127.0.0.1:6379> smembers u:1:f
1) "movies"
2) "sports"
实战:
1.微博抽奖行动。
把用户都放在一个集合里面。在抽奖的时候随机的弹出几个用户。抽奖完成后删除集合即可。
2.标签
sadd user1:tags tag1 tag2 tag3
sadd user2:tags tag1 tag2 tag3
sadd tag1:users user1 user3
sadd tag2:users user4 user3 user2
两个其实是一个事务。
sdiff key1 key2 差集
sinter key1 key2 并集
sunion key1 key2 合集
sdiff|sinter|suion + store destkey 将结果存入destkey中
比如关注的好友。也可以使用集合来做。
sadd = tagging 标签
spop/srandmember = random item 随机元素
sadd + sinter = social graph 社交关系图
127.0.0.1:6379> sadd user1 it ot dt st ab
(integer) 4
127.0.0.1:6379> sadd user2 aa ab ac ad it
(integer) 4
127.0.0.1:6379> smembers user1
1) "st"
2) "it"
3) "ot"
4) "dt"
127.0.0.1:6379> smembers user2
1) "ad"
2) "aa"
3) "ac"
4) "ab"
127.0.0.1:6379> sdiff user1 user2
1) "st"
2) "ot"
3) "dt"
127.0.0.1:6379> sinter user1 user2
1) "it"
2) "ab"
127.0.0.1:6379> sunion user1 user2
1) "it"
2) "ac"
3) "ot"
4) "dt"
5) "ab"
6) "ad"
7) "aa"
8) "st"
第五章 ZSET
zset有序集合,日常用的比较少。
key score value
user:ranking 1 kris
91 mike
200 frank
value部分由两部分组成。score一个分数的概念,按照分值的顺序组成。 可以排序,可以按照范围来取结果
与集合的相同点和不同点
集合:无重复元素,无序,只有elements元素
有序结合:无重复元素,有序,由elements+score组成
与列表的相同点和不同点
列表:可以重复,有序,elements
有序结合:不允许重复,有序,elements+score
以Z开头
zadd key score element 添加,score可以重复,elements不可以重复。可以添加多对。o(logn)
zrem key element 删除,不需要score。因为是不重复的,可以删除多个element o(1)。
zscore key element 获得element的score
zincrby key increScore element 增加或者减少score,减少是因为可以传入负数 o(1)
zcard key 返回元素的总个数,redis内部自动计算key的元素个数 o(1)
zrank key elements 获得元素的排名
zrange key start end [withscores] 获得指定范围的升序元素,withscore是否按照分值打印 o(log(n)+m)
zrangebyscore key minScore maxScores [withscorses] 返回指定范围内分数范围的升序元素
o(log(n)+m) [withsore 添加就打印分值,不添加就打印元素]
zcount key minScore maxScore 返回有序集合内指定分数范围的个数o(log(n)+m)
zremrangebyrank key start end 按照范围排序来删除元素。o(log(n)+m)
zremrangebyscore key minScore maxScore 删除指定分数内的升序元素 o(log(n)+m)
zrevrank 从高到低排名
zrevrange 从高到低排名去一个范围
zrevrangebyscore 从高到低排名获取一个范围的结果
zinterstore 对两个有序集合间交集的结果计算,并存储。
zunionstore 对两个有序集合间并集的结果计算,并存储。
sadd 新增
127.0.0.1:6379> zadd uzet 100 english
(integer) 1
127.0.0.1:6379> zadd uzet 100 swimming
(integer) 1
127.0.0.1:6379> zadd uzet 100 math
(integer) 1
127.0.0.1:6379> zadd uzet 101 math
(integer) 0
127.0.0.1:6379> zadd uzet 100 math2
(integer) 1
127.0.0.1:6379> zadd uzet 90 math3
(integer) 1
127.0.0.1:6379> zadd uzet 80 math4
(integer) 1
127.0.0.1:6379> zadd uzet 45 math5
(integer) 1
获得元素的分数
127.0.0.1:6379> zscore uzet math5
"45"
对分数进行增加和减少
127.0.0.1:6379> zincrby uzet 15 math5
"60"
127.0.0.1:6379> zincrby uzet -15 math5
"45"
统计集合的元素个数
127.0.0.1:6379> zcard uzet
(integer) 7
获得元素排名
127.0.0.1:6379> zrank uzet math5
(integer) 0
127.0.0.1:6379> zrank uzet math4
(integer) 1
127.0.0.1:6379> zrank uzet math3
(integer) 2
127.0.0.1:6379> zrank uzet math2
(integer) 4
获得指定元素的升序排名
127.0.0.1:6379> zrange uzet 0 4
1) "math5"
2) "math4"
3) "math3"
4) "english"
5) "math2"
获得指定元素的升序排名并打印分数
127.0.0.1:6379> zrange uzet 0 4 withscores
1) "math5"
2) "45"
3) "math4"
4) "80"
5) "math3"
6) "90"
7) "english"
8) "100"
9) "math2"
10) "100"
获得指定升序分数范围内的元素并打印分值
127.0.0.1:6379> zrangebyscore uzet 80 90 withscores
1) "math4"
2) "80"
3) "math3"
4) "90"
返回有序集合内指定分数的个数。
127.0.0.1:6379> zcount uzet 100 100
(integer) 3
从高到底获得元素排名
127.0.0.1:6379> zrevrank uzet math4
(integer) 5
127.0.0.1:6379> zrevrank uzet math5
(integer) 6
指定元素范围从高到底排名
127.0.0.1:6379> zrevrange uzet 0 -1
1) "math"
2) "swimming"
3) "math2"
4) "english"
5) "math3"
6) "math4"
7) "math5"
根据分数降序获得元素排名
127.0.0.1:6379> zrevrangebyscore uzet 90 45
1) "math3"
2) "math4"
3) "math5"
删除一个元素,无需带分数,因为分数是不重复的。
127.0.0.1:6379> zrem uzet math
(integer) 1
删除指定排名内的元素
127.0.0.1:6379> zremrangebyrank uzet 0 1
(integer) 2
删除指定分数区间的元素
127.0.0.1:6379> zremrangebyscore uzet 100 100
(integer) 3
实战:
1.排行榜
新书榜,新歌榜。
zadd 分数添加
zincrby 分数的更新
zrem 删除
zrangebyscore 获取一定范围的榜单
新歌新单都可以使用时间戳 score timestamp saleCount followCount
也可以对多天的榜单进行一个汇总,交集,并集,合集。