Redis(Remote Dictionary Service) --- 远程字典服务
Redis的五种数据结构:string(字符串),list(列表),hash(哈希),set(集合),zset(有序集合)
Redis之所以称为远程字典服务是因为他的所有数据结构都是由K-V形式组成的,以唯一的key作为名称,来获取对应的value。
注意:不同的数据结构,实际上就是不同的Value结构。
String:
Redis的字符串是动态字符串,可以修改,采用预分配冗余空间的方式来减少内存的频繁分配。
扩容规则:小于1MB扩大一倍,大于1MB每次扩大1MB,字符串最大的长度为512MB。
#添加操作 --- 可覆盖
set key value
set name codehole
#取值操作
get key
get name
#判断是否存在,如果存在返回1,如果不存在返回0
exists key
exists name
#批量添加
mget key1 value1 key2 value2 key3 value3
mset name1 boy name2 girl name3 unknown
#批量获取
mget key1 key2 key3
mget name1 name2 name3
#过期时间设置 --- 相当于定时删除
expire key time (以秒为单位)
expire name 5 (key为name的元素在5秒后过期)
#set+expire的等价形式 setex
setex key time value
setex name 5 codehole
#创建操作 如果setnx的key已经存在则返回0,不进行任何操作,不覆盖原值。如果key不存在,则等价于正常的set创建,返回值为1
setnx key value
setnx name codehole
#返回字符串的长度 ---strlen
strlen key
strlen name
#value为数值时的自增操作---incr,incrby
incr key (返回值为key对应的value+1)
incrby key num (返回值为key对应value+num)
#注意:自增范围不能超过signed long,num可以为负数,相当于减法
List:
Remote Dictionary Service中的列表其实是由链表形成的,本链表是双向链表。
注意:插入和删除的时间复杂度为O(1),索引定位时间复杂度为O(n)。
由Redis的双向链表形成的两种Redis数据结构----队列和栈
队列:右进左出,先进先出,利用list语句中的rpush,lpop实现。
注意:添加元素时,均为从右边进入。
堆栈:右进右出,先入先出,利用list语句中的rpush,rpop实现。
#添加语句--rpush
rpush key value1 value2 value3
rpush books java python golang
#左删除元素---lpop key
lpop key #弹出第一个从左边删除的元素
lpop books
#右删除元素---rpop key
rpop key #弹出第一个从右边删除的元素
rpop books
由于Redis中list的数据结构为双向链表,所以无法通过索引来进行定位,只能通过遍历的方式,这样时间复杂度为O(n),在数据量很大的时候,操作时间较长,称为慢操作,慢操作包含以下内容:
#通过索引取值---lindex
#注意:虽然说是通过索引取值,但是它无法直接取值,而是通过遍历的方式
#这里还需要注意的是,index是可以为负数的,-1为倒数第一个元素,-2为倒数第二个元素
lindex key index
lindex books 0 #获取key为books的第0个元素
#获取区间内索引的值---ltrim
#定义了一个区间[start_index,end_index],对区间内的值进行保留,其余的全部刨除
ltrim key start_index end_index
ltrim books 1 0 #当start_index大于end_index时,相当于清空所有元素
#获取列表的长度 ---llen
llen key
llen books
#读取区域内的列表内容,区域为[start_index,end_index]
lrange key start_index end_index
lrange books 0 -1 #0到-1为遍历所有的元素
Dict:
Redis的dict通俗来讲就是字典形式,内部存储许多键值对,与广义上的字典不同的是,Redis的字典只能存储字符串,而且与Java中的HashMap采用了不一样的hash方式。
注意:对于正常的字典来说,rehash的方式是直接将全部旧的哈希表的内容迁移到新表之中,但是对于Redis来说,像rehash这种耗时的操作或许会导致线程阻塞,从而导致服务器宕机,所以Redis采用了一种不同的rehash方式---渐进式的rehash
渐进式rehash:这种rehash的方式会在rehash的同时,保留新旧两个rehash结构,查询时会同时查询两个hash结构,在后续的定时任务以及hash操作只能中,循序渐进的将旧的hash内容慢慢迁移到新的hash中,当全部迁移结束之后,删除旧的hash,用新的hash取而代之。
hash功能:存储用户信息,优点是可以分字段存储,缺点是存储的消耗量很大。
#添加键值对 ---hset
#注意:只能添加一对键值对,不能像rpush一样添加多个,想要添加多个需要使用hmset
hset key hashkey hashvalue
hset books java "think in java"
#一次性添加多个键值对 ---hmset
hmset key hashkey1 hashvalue1 hashkey2 hashvalue2...
hmset books java "think in java" python "python games" #注意字段中有括号时,需要加上双引号
#读取字典全部键值对 --- hgetall
hgetall key
hgetall books
#读取键值对 ---hget
#和hset一致,只能够读取一个hashkey所对应的value,想要读取多个需要使用hmget
hget key hashkey
hget book java
#读取多个键值对 ---hmget
hmget key hashkey1 hashkey2 hashkey3
#读取dict中的数据个数 ---hlen
hlen key
hlen book
#删除字典中的键值对 ---hdel
hdel key hashkey
hdel book java
#自增以及加法 ---hincrby
#需要注意的是,虽然dict中的值都是字符串形式,但是可以对value中以字符串形出现的数据量进行加法
#注意:如果检测到value值非数字,则会报错,如果hashkey不存在,则会建立对应的hashkey,值为num
hincrby key hashkey num
hincrby person age 1
Set:
Redis中的set数据类型其实也是一种键值对的形式,内部是无序的,唯一的键值对,只不过set集合中的所有的value都是null。set结构可以用来存储活动中奖的用户ID,因为有去重的功能,可以保证一个用户不会中奖两次。
#添加元素 ---sadd
#注意:在添加元素时,会自动监测元素的key是否已经存在在set中,如果已经存在,则会返回0且不再添加,如果不存在则会返回1,并且将其添加到集合中
sadd key setkey1 setkey2 setkey3
sadd books python
#sadd与rpush相同,可以添加多个元素
sadd books python java c++ golang
#读取显示集合中所有元素
#读取的顺序可能与存入的顺序不同,因为set是无序的
smembers key
#查询是否存在 ---sismember
#如果存在则返回1,如果不存在则返回0
sismember key setkey
sismember book java
# 获得集合的长度 ---scard
#相当于list中的llen,hash中的hlen
scard key
scard book
#删除集合中的元素 ---srem
srem key setkey
srem book java
#随机弹出并删除一个元素 ---spop
spop key
spop book
Zset:
Redis中的Zset应该是最有特色的数据结构了,它的中文名称是有序列表,他既有集合的唯一性,又将无序性去掉,采用score的方式来排序,它的内部是由跳表构成的,跳表我们以后再说。
Zset的功能很多,他可以存储粉丝列表,还能存储学生成句,并且按照所需的方式排列。
#添加元素 ---zadd
#zadd和sadd,rpush一样可以一次性添加多个元素
#而字符串中的set和字典中的hset则不能,需要使用mset和hmset
zadd key score value
zadd books 9.0 "think in java"
#按照成绩排名输出 --- zrange
#几乎与列表中的lrange相同,不再赘述
zrange key start_index end_index
zrange books 0 -1
#按照成绩排名的逆序进行输出 --- zrevrange
zrevrange key start_index end_index
zrevrange books 0 -1
#计算有序集合的长度 ---zcard
#与scard的功能用法相同
zcard key
zcard books
#获取指定value的score ---zscore
#返回值为value所对应的分数,分数内部的存储形式为double所以存在小数点的精度问题
zscore key value
zscore book java
#获取某元素在有序列表中的排名 ---zrank
#返回值为对应的排名,需要特别注意的是,第一位是0,从低到高排序
zrank key value
zrank book java
#获取某元素在有序列表中的排名 ---zrevrank
#从高到低排序
zrevrank key value
zrevrank book java
#分值区间内遍历有序列表 ---zrangebyscore
# inf代表infinite 代表无穷大 顺序为从小到大
zrangebyscore key lowscore highscore
zrangebyscore book 0 8.9
zrangebyscore book 0 8.9 withscores
#删除元素 ---zrem
zrem key value
zrem book java
#给成员增加指定分数 ---zincrby
zincrby key num value
zincrby book 1 java
#返回在指定分数区域内的元素个数 ---zcount
zcount key lowscore highscore
zcount book 8 9
#删除指定成绩区间的元素 ---zremrangebyscore
zremrangebyscore key lowscore highscore
zremrangebysocre book 8 9
#删除指定排名区间的元素 ---zremrangebyrank
zremrangebyrank key lowrank highrank
zremrangebyrank book 1 2