ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
之前安装好了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 获得字段数量