redis支持5种数据类型:string、hashes、lists、sets、sorted set
STRING数据类型
string是最简单的类型,一个key对应一个value。string类型是二进制安全的。意思是redis的string可以包含任何数据,比如jpg图片或者序列化对象。同时string类型可以呗部分命令按int处理,比如incr等命令。常用的string命令:
1、set set key value
将字符串值value关联到key。
如果key已经持有其他值,SET就覆写旧值,无视类型。
总是返回OK,因为SET不可能失败。
2、setnx setnx key value
与set类似,为key设置value,是set if not exists的缩写,不同之处在于当key已经存在时,不会修改key的值,并返回值0
返回值:成功1;失败0
3、setex set key seconds value
将value关联到key,并为key设置过期日期seconds,以秒为单位,如果key存在,则覆盖原值
4、setrange set key offset value
用value参数复写给定key所存储的字符串,从偏移量offset开始,不存在的key当作空白字符串处理。setrange命令会确保字符串足够长以便将value在指定的偏移量上。如果给定key原来储存的字符串长度比偏移量小(比如字符串只有5个字符长,但你设置的offset是10),那么原字符和偏移量之间的空白将用零比特(zerobytes,"\x00")来填充。
5、mset mset key1 v1 key2 v2...
同时对多个key进行赋值,当发现同名的key时,mset会将新值覆盖旧值。mset是一个原子性(automic)操作,同时改变所有key的值,绝对不会发生改变一部分值,而另一部分没发生改变的情况。
6、msetnx msetnx key1 v1 key2 v2...
同时对多个key进行赋值,当发现同名key时,msetnx会拒绝所有key传值的操作。mset也是一个原子性操作。
7、get get key
返回key所关联的字符串,如果key不存在,则返回特殊值nil,如果key存储的不是字符串类型,返回一个错误,因为get只能处置字符串值
8、getset getset key value
将给定key的值设置为value,并返回key的旧值。若key不存在旧值,返回nil,若key旧值不是字符串类型时,返回错误
9、getrange getrange key start end
返回key中字符串的子字符串,字符串的截取范围由start和end两个偏移量决定(包括start和end在内)。负数偏移量表示从字符串最后开始计算,如-1表示最有一个字符。getrange通过保证子字符串的值域(range)不超过实际字符串的值域来处理超出范围的值域的请求,如果超出,超过部分自动忽略。
10、mget mget key1 key2 key3...
一次获取多个key关联的值,如果某个key不存在,则该key返回特殊的值nil
incr incr key
对key对应的值做++操作,如果key不存在,以0作为key的初始值,然后执行++。如果key的值包含一个错误类型,或不能表示数字,则返回一个错误。
11、incrby incrby key increment
将key存储的值加上增量increment,如果key不存在,以0作为初始值,然后进行incrby操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
12、derc derc key
同incr一样,做--操作
13、dercby derc key increment
同incrby一样,做--操作
14、append append key value
如果key已经存在,并且是个字符串,append就将value追加到key原值后面,如果不存在,就只是简单的将value设定给key,同set key value一样。
15、strlen strlen key
返回key所存储的字符串值的长度,当key存储的不是字符串时,返回一个错误。若key不存在,返回0
HASH数据类型
Redis hash是一个string类型的field和value的映射表.它的添加、删除操作都是O(1)(平均)。hash特别适合用于存储对象。相较于将对象的每个字段存成单个string类型。将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。省内存的原因是新建一个hash对象时开始是用zipmap(又称为small hash)来存储的。这个zipmap其实并不是hash table,但是zipmap相比正常的hash实现可以节省不少hash本身需要的一些元数据存储开销。尽管zipmap的添加,删除,查找都是O(n),但是由于一般对象的field数量都不太多。所以使用zipmap也是很快的,也就是说添加删除平均还是O(1)。如果field或者value的大小超出一定限制后,Redis会在内部自动将zipmap替换成正常的hash实现. 这个限制可以在配置文件中指定
hash-max-zipmap-entries 64 #配置字段最多64个。
hash-max-zipmap-value 512 #配置value最大为512字节。
1、hset
设置hash field为指定值,如果key不存在,则先创建。
2、hsetnx
设置hash field为指定值,如果key不存在,则先创建。如果field已经存在,返回0,nx是not exist的意思。
第一次执行是成功的,但第二次执行相同的命令失败,原因是field已经存在了。
3、hmset
同时设置hash的多个field。
4、hget
获取指定的hash field。
5、hmget
获取全部指定的hash filed。
6、hincrby
指定的hash filed 加上给定值。
在本例中我们将field3的值从20降到了12,即做了一个减8的操作。
7、hexists
测试指定field是否存在。
8、hlen
返回指定hash的field数量。
9、hdel
返回指定hash的field数量。
10、hkeys
返回hash的所有field。
11、hvals
返回hash的所有value。
12、hgetall
获取某个hash中全部的filed及value。
LIST数据类型
list是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等,操作中key理解为链表的名字。
Redis的list类型其实就是一个每个子元素都是string类型的双向链表。链表的最大长度是(2的32次方)。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素。这使得list既可以用作栈,也可以用作队列。
有意思的是list的pop操作还有阻塞版本的,当我们[lr]pop一个list对象时,如果list是空,或者不存在,会立即返回nil。但是阻塞版本的b[lr]pop可以则可以阻塞,当然可以加超时时间,超时后也会返回nil。为什么要阻塞版本的pop呢,主要是为了避免轮询。举个简单的例子如果我们用list来实现一个工作队列。执行任务的thread可以调用阻塞版本的pop去获取任务这样就可以避免轮询去检查是否有任务存在。当任务来时候工作线程可以立即返回,也可以避免轮询带来的延迟。说了这么多,接下来看一下实际操作的方法吧:
1、lpush
在key对应list的头部添加字符串元素
2、rpush
在key对应list的尾部添加字符串元素
3、linsert
在key对应list的特定位置之前或之后添加字符串元素
4、lset
设置list中指定下标的元素值(下标从0开始)
5、lrem
从key对应list中删除count个和value相同的元素。
count>0时,按从头到尾的顺序删除,具体如下
count<0时,按从尾到头的顺序删除,具体如下
count=0时,删除全部,具体如下
6、ltrim
保留指定key 的值范围内的数据
7、lpop
从list的头部删除元素,并返回删除元素
8、rpop
从list的尾部删除元素,并返回删除元素
9、rpoplpush
从第一个list的尾部移除元素并添加到第二个list的头部,最后返回被移除的元素值,整个操作是原子的.如果第一个list是空或者不存在返回nil
10、lindex
返回名称为key的list中index位置的元素
11、llen
返回key对应list的长度
SET数据类型
set是集合,和我们数学中的集合概念相似,对集合的操作有添加删除元素,有对多个集合求交并差等操作,操作中key理解为集合的名字。
Redis的set是string类型的无序集合。set元素最大可以包含(2的32次方)个元素。
set的是通过hash table实现的,所以添加、删除和查找的复杂度都是O(1)。hash table会随着添加或者删除自动的调整大小。需要注意的是调整hash table大小时候需要同步(获取写锁)会阻塞其他读写操作,可能不久后就会改用跳表(skip list)来实现,跳表已经在sorted set中使用了。关于set集合类型除了基本的添加删除操作,其他有用的操作还包含集合的取并集(union),交集(intersection),差集(difference)。通过这些操作可以很容易的实现sns中的好友推荐和blog的tag功能。下面详细介绍set相关命令:
1、sadd
向名称为key的set中添加元素
2、srem
删除名称为key的set中的元素member
3、spop
随机返回并删除名称为key的set中一个元素
4、sdiff
返回所有给定key与第一个key的差集
5、sdiffstore
返回所有给定key与第一个key的差集,并将结果存为另一个key
6、sinter
返回所有给定key的交集
7、sinterstore
返回所有给定key的交集,并将结果存为另一个key
8、sunion
返回所有给定key的并集
9、sunionstore
返回所有给定key的并集,并将结果存为另一个key
10、smove
从第一个key对应的set中移除member并添加到第二个对应set中
11、scard
返回名称为key的set的元素个数
12、sismember
测试member是否是名称为key的set的元素
13、srandmember
随机返回名称为key的set的一个元素,但是不删除元素
sorted sets数据类型
sorted set是set的一个升级版本,它在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解为有两列的mysql表,一列存value,一列存顺序。操作中key理解为zset的名字。
和set一样sorted set也是string类型元素的集合,不同的是每个元素都会关联一个double类型的score。sorted set的实现是skip list和hash table的混合体。
当元素被添加到集合中时,一个元素到score的映射被添加到hash table中,所以给定一个元素获取score的开销是O(1),另一个score到元素的映射被添加到skip list,并按照score排序,所以就可以有序的获取集合中的元素。添加,删除操作开销都是O(log(N))和skip list的开销一致,redis的skip list实现用的是双向链表,这样就可以逆序从尾部取元素。sorted set最经常的使用方式应该是作为索引来使用.我们可以把要排序的字段作为score存储,对象的id当元素存储。下面是sorted set相关命令
1、zadd
向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序
2、zrem
删除名称为key的zset中的元素member
3、zincrby
如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment
4、zrank
返回名称为key的zset中member元素的排名(按score从小到大排序)即下标
5、zrevrank
返回名称为key的zset中member元素的排名(按score从大到小排序)即下标
6、zrevrange
返回名称为key的zset(按score从大到小排序)中的index从start到end的所有元素
7、zrangebyscore
返回集合中score在给定区间的元素
8、zcount
返回集合中score在给定区间的数量
9、zcard
返回集合中元素个数
10、zscore
返回给定元素对应的score
11、zremrangebyrank
删除集合中排名在给定区间的元素
12、zremrangebyscore
删除集合中score在给定区间的元素