redis学习笔记(三)——五种数据结构的理解和使用
字符串
字符串的结构和适用场景
先看一下字符串的键值结构:
对于redis来说,所有的key都是字符串类型的,但value的类型各有不同(五种主要数据类型)。
和js一样,数字、二进制、json等等也属于string类型。
字符串的主要使用场景包括缓存、计数器、分布式锁等等。
字符串的常用命令
基本命令
get key
// 获取key对应的value
set key value
// 设置key-value
del key
// 删除key-value
计数相关的命令(value可以存整形)
incr key
// key自增1,如果key不存在,自增后get(key)=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
上图可以看到,当某key内数据不为整形时,会报错
incr、decr对于网站的计数是非常好用的,如统计访问量、点击量。
set相关命令
set key value
// 不管key是否存在,都设置
setnx key value
// key不存在,才设置
set key value xx
// key存在,才设置
nx其实就相当于增加,xx相当于更新操作。这对于实际使用上也很有帮助。
mget mset 批量操作
mget key1 key2 key3
// 批量获取key 原子操作
mset key1 value1 key2 value2 key3 value3
// 批量设置key-value
这里介绍一下mget和普通get的区别,如果我们要获取n个值,那么实际所花费时间为n次网络时间+n次命令时间
但如果使用mget,所花费时间为1次网络时间和n次命令时间,耗时大大减少
当然mget不能一次get无限个,应该适当使用。
另外备注一下,mset也是原子操作,这个命令的使用不会导致一部分数据被修改另外一部分未被修改(中断时)。
其他操作
getset key newvalue
// set key newvalue 并返回旧的value
append key value
// 将value追加到旧的value
strlen ken
// 返回字符串的长度(注意中文,中文占用的不是一个字节)
incrbyfloat key 3.5
// 增加key对于的浮点数 3.5
getrange key start end
// 获取字符串指定下标所有的值
setrange key index value
// 设置指定下标所有对应的值
hash
hash的键值结构
hash自然也是key-value类型。key值为字符串,value则分为两个:field和value。vield代表属性,value代表对应的值。
其实就相当于直接存储了一个对象,我们可以直接向这个对象添加属性。
如果是string,string储存对象,那么常用的方法是将对象序列化为json格式存储,需要增加属性则取出来,反序列化后添加属性再序列化存进去。
数据结构如下:
可以理解为存储了一张表:
hash的特点
- smallredis。可以这么理解,redis本来就是一个key-value类型,hash又是一个key-value。
- field不能相同,value可以相同。
重要API
H:所有哈希命令都以h开头。
hget key field
// 获取hash key对应的field的value
hset key field value
// 设置hash key对应field的value
hdel key field
// 删除hash key对应field的value
hexists key field
// 判断hash key是否有field
hlen key
// 获取hash key field的数量
hmget key field1 field2……
// 批量获取hash key的一批field对应的值
hmset key field1 value1 field2 value2……
// 批量设置hash key的一批field value
效果其实和mget、mset一样
hgetall key
// 返回hash key对应所有的field和value
hvals key
// 返回hash key对应所有field的value(只返回值)
hkeys key
// 返回hash key对应所有field
pic11
同样的,小心使用hgetall。牢记redis是单线程。
hsetnx key field value
// 设置hash key对应field的value(如field已经存在,则失败)
hincrby key field intCounter
// hash key对应的field的value自增intCounter
hincrbyfloat key field floatCounter
// hincrby浮点数版
string vs hash
相似的api自然不用多说:
以存储一个用户的信息为例子,如果我们使用string类型,那么会将其信息序列化后存入redis。但这样每次增加删除都需要进行序列化和反序列化的操作。
另外一个存储方法,就是每个key代表一个属性。只是这样每个对象就分离开了,不是一个整体。相应的,它可以单独操作某属性。
而用hash就比较直观了,能满足上述两个优点,而且实际是能够节省很多内存的:
3种方案的优缺点:
- 方案一——string存储序列化数据:优点:编程简单、可能节约内存;缺点:序列化开销、设置属性要操作整个数据。
- 方案二——string分开储存属性:优点:直观、可以部分更新;缺点:内存占用较大、key较为分散。
- 方案三——hash:优点:直观、节省空间、可以部分更新;缺点:编程较为复杂,且过期时间不好设置。无法直接办到对hash中某个属性添加过期时间的设置。
列表
列表的key实际上就是一个常见的有序队列。列表是有序的可以重复的数据结构,并且可以在两边插入或是弹出。
重要api
列表的大多api都是以l为开头。
增
rpush key value1 value2……
// 从列表右端插入值
lpush key value1 value2……
// 从列表左边插入值
linsert key before|after value newValue
// 在list指定的值前|后插入newValue
删
lpop key
// 从列表左侧弹出一个item
rpop key
// 从列表右侧弹出一个item
lrem key count value
// 根据count值,从列表中删除所有value相等的值。
// count > 0,从左到右,删除最多count个value相等的值
// count < 0,从右到左,删除最多Math.abs(count)个value相等的值
// count=0,删除所有value相等的值
ltrim key start end
// 按照索引范围修建列表
查
lrange key start end
// 获取列表制定索引范围所有item,包含end
lindex key index
// 获取列表指定索引的item
llen key
// 获取列表长度
改
lset key index newValue
// 设置列表指定索引值为newValue
其他
blpop/brpop key timeout
// lpop/rpop 阻塞版本,timeout是阻塞超时时间,timeout=0为永远不阻塞。比如要取一个空队列,lpop直接返回,但是blpop会保持等待,直到有数据或是时间到了。
实际使用
比如timeline(按时间排序的微博),就可以用列表来进行存储。
集合set
集合的数据结构
对于集合,key仍然是字符串,但是value就是一个集合,它会将所有字符串做一个组合。
集合支持集合间的api。集合不允许插入重复元素。集合是无序的。
集合的常用API
集合命令以s开头。
sadd key element
// 向集合key添加element(如果element已经存在,添加失败)
srem key element
// 将集合key中的element移除掉
scard key
// 计算集合大小
sismember key element
// 判断value是否在集合中
srandmember key count
// 从集合中随机挑count个元素
spop key
// 从集合中随机弹出一个元素
smembers key
// 获取集合所有元素(无需返回,小心使用)
集合可以用来使用于抽奖、点赞系统、tag系统等。
集合间api:
sdiff key1 key2
// 得到差集
sinter key1 key2
// 得到交集
sunion key1 key2
// 得到并集
sdiff|sinter|sunion + store destkey
// 将对于得到的集合保存在destkey中
有序集合
有序集合是一种比较新的结构,平常接触较少。
特点和数据结构
有序集合的value也为两部分,分为score和value。它按照score来进行一个排序。
集合和有序集合的区别,具体可以用如下图所示:
列表和有序集合的区别,具体可以用如下图所示:
重要api
有序集合都是以z开头的。
zadd key score element
// 添加score和element(score可以重复,element不能重复)
zrem key element(可以是多个)
// 删除元素
zscore key element
// 返回元素的分数
zincrby key increScore element
// 增加或减少元素的分数
zcard key
// 返回元素的总个数
zrange key start end
// 返回指定索引范围内的升序元素(索引指的是按照分值排序得到的排名)
zrangebyscore key minScore maxScore
// 返回指定分数范围内的升序元素
zcount key minScore maxScore
// 返回有序集合内在指定分数范围内的个数
zremrangebyrank key start end
// 删除指定排名内的升序元素
zremrangebyscore key minScore maxScore
// 删除指定分数内的升序元素
实际使用
有序集合比较常见的使用场景为排行榜