之前安装好了Redis之后,对于如何使用,还不是特别清楚,因此百度了下,同时结合了下自己常用的命令,做了下整合,
**以下是一些相关常用的命令;**
# 1 Redis数据类型及应用场景
Redis最为常用的数据类型主要有以下五种:
· String
· Hash
· List
· Set
· Sortedset
- 下图为Redis内部内存管理中是如何描述这些不同数据类型的:
![](https://box.kancloud.cn/2016-06-03_575103fb53756.jpg)
- 首先Redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示:type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:"123" "456"这样的字符串。
- 这里需要特殊说明一下vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的,该功能会在后面具体描述。通过上图我们可以发现Redis使用redisObject来表示所有的key/value数据是比较浪费内存的,当然这些内存管理成本的付出主要也是为了给Redis不同数据类型提供一个统一的管理接口,实际作者也提供了多种方法帮助我们尽量节省内存使用,我们随后会具体讨论。
### 1.1String类型
**常用命令:**
set,get,decr,incr,mget等。
**应用场景:**
String是最常用的一种数据类型,普通的key/value存储都可以归为此类,这里就不所做解释了。
**实现方式:**
String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
### 1.2List类型
**常用命令:**
lpush,lpop,rpop,lrange等。
**应用场景:**
Redislist的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现,比较好理解,这里不再重复。
**实现方式:**
Redislist的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
### 1.3Set类型
**常用命令:**
sadd,spop,smembers,sunion等。
**应用场景:**
Redisset对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
**实现方式:**
set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。
### 1.4Sorted Set类型
**常用命令:**
zadd,zrange,zrem,zcard等
**使用场景:**
Redissorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
**实现方式:**
Redissorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
### 1.5Hash类型
**常用命令:**
hget,hset,hgetall等。
**应用场景:**
我们简单举个实例来描述下Hash的应用场景,比如我们要存储一个用户信息对象数据,包含以下信息:
用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:
![](https://box.kancloud.cn/2016-06-03_575103fb75732.jpg)
第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。
![](https://box.kancloud.cn/2016-06-03_575103fb8adf1.jpg)
第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。
那么Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口,如下图:
![](https://box.kancloud.cn/2016-06-03_575103fba50f9.jpg)
也就是说,Key仍然是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。
这里同时需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而另其它客户端的请求完全不响应,这点需要格外注意。
**实现方式:**
上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
# 2 Redis数据类型相关命令
### 2.1String命令
字符串数据类型 string
字符串类型是redis基本数据类型,能存储任何形式的字符串,包括二进制数据。
set key value 赋值
get key 取值
incr key 递增数字(所有redis命令都是原子操作)
redis键命名实践 “对象类型:对象id:对象属性”,对于多个单词推荐用.分割。如键user:1:friends表示id为1的用户的好友列表。
incrby key increment 增加指定整数
decrby key decrement 减少指定的整数
incrbyfloat key increment 增加指定浮点数
append key value 向尾部追加值,返回追加后字符串的长度
strlen key 返回键值的长度
mget key [key ...] 获取多个健值
mset key value [key value ...] 设置多个键值
位操作
getbit key offset 获得一个字符串指定位置的二进制位的值(0或1)
setbit key offset value 设置字符串类型键指定位置的二进制值,返回该位置的旧值
bitcount key [start] [end] 统计字符串类型中值为1的二进制位个数,可以指定字节的范围
bitop operation destkey key [key...] (and, or, xor, not)
### 2.2List命令
列表类型可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素或者获得某个列表的某一个片段。
内部使用双向链表实现,获取越接近两端的元素速度就越快,不过索引访问元素比较慢。列表类型能非常快速地完成关系数据库难以应付的场景,如社交网络新鲜事。
lpush key value [value...] 从列表左边增加元素
rpush key value [value...] 从列表右边增加元素
lpop key 从列表左边弹出元素
rpop key 从列表右边弹出元素
llen key 获取列表中元素的个数
lrange key start stop 获取列表片段(包括stop,支持负数表示从最右边开始计数)
lrem key count value 删除前count个值为value的元素(count>0时从左边开始删除,count<0从右边开始删除,count=0删除所有为value的元素)
lindex key index 获取指定索引的元素值
lset key index value 设置指定索引的元素值
ltrim key start end 只保留指定片段
linsert key fefore|after pivot value 首先从左到右查找pivot元素,再根据第二个参赛将value插入该元素前面或后面。
rpoplpush source destination 将一个元素转移到另一个列表 ,原子操作。当source和destination相同时会不断将对尾元素移到队首,实现网站监控系统。
### 2.3Set命令
集合类型每个元素不同,且无序。
sadd key member [member...] 增加元素,返回成功加入元素的个数
srem key member [member...] 删除元素
smembers key 获得集合中所有元素
sismember key member 判断是否存在集合中
集合间运算
sdiff [destination] key [key ...] 多个集合求差运算a-b,并存储到destination中
sinter [destination] key [key ...] 多个集合执行交运算
sunion [destination] key [key...] 多个集合求并运算
scard key 集合中元素个数
srandmemeber key [count] 随机获得集合中元素(当count>0时随机获取count个不重复元素,count<0时不保证重复)
spop key 从集合中随机弹出一个元素
### 2.4Sorted Set命令
列表类型通过链表实现,获取靠近两端的数据速度极快,当元素增加后中间元素比较慢,更适合"新鲜事"或“日志”这样很少访问中间元素的应用。
有序集合类型通过散列表和跳跃表实现的,所以即使读取位于中间位置也很快o(nlgn)。
列表中不能简单调整某个元素位置,有序集合可以。有序集合更耗费内存。
zadd key score member [score member...] 加入一个元素和该元素的分数(分数可以是整数或小数,+inf和-inf表示正负无穷)
zscore key member 获得元素的分数
zrange key start stop [withscore] 按照从从小到大的顺序返回start和stop之间所有元素(withscore表示带上分数)复杂度o(logn+m)
zrevrange key start stop [withscore] 从大到小的顺序
zrangebyscore key min max [withscore] [limit offset count] 按照从小到大返回分数在min和max之间的元素
zincrby key increment member 增加某个元素的分数
zcard key 获得集合中元素个数
zcount key min max 获得指定范围内的元素个数
zrem key member [member ...] 删除一个或多个元素
zremrangebyrank key start stop 按照元素分数从小到大的顺序删除指定排名范围内的所有元素,并返回删除元素的个数
zremrangebyscore key min max 删除指定分数范围内的所有元素
zrank key member 获得元素的排名
zrevrank key member
### 2.5Hash命令
散列类型的键值也是一种字典结构,其存储了字段和字段值的映射,但字段值只能是字符串,不支持其他类型。(集合类型也不支持数据类型嵌套)
hset key field value 赋值(插入时返回1,更新时返回0)
hget key field 取值
hmset key field value [field value ...]
hmget key field [feild...]
hgetall key
hexists key field 判断字段是否存在
hsetnx key field value 当字段不存在时赋值
hincrby key field increment 增加数字
hdel key field [field...] 删除字段
hkeys key 只获取字段名
hvals key 只获取字段值
hlen key 获得字段数量