一、Redis常用命令
(1)keys * :遍历所有的key(在生产环境一定要禁止使用该命令,由于生产环境会保存很多的缓存数据,而且redis是单线程的,如果使用该命令容易让redis堵塞,甚至让服务器宕机)。
(2)keys [pattern] :根据匹配条件来匹配对应的key。例如:
(3) dbsize :计算key的总数(在生产环境该命令可以使用,该命令不会去遍历redis保存的所有key来计算总数,而是redis内置了一个计数器,它会实时的更新redis保存key的总数,所以该命令能再生产环境中使用)。
(4)exists key :检查key是否存在,如果存在则返回1,不存在则返回0(一般情况下该命令能再生产环境中使用)。
(5)del key :删除指定的key,如果key存在则删除成功返回1,如果key不存在则删除失败返回0。
(6)expire key second :设置key在多少秒内过期。
(7)ttl key :查看key的剩余过期时间。如果返回的值大于0则表示这个key的剩余过期时间,如果返回值为-1则表示这个key没有过期时间,如果返回值等于-2则表示这个key不存在(已经过期)
(8)persist key :去掉key的过期时间。
(9)type key :返回key的类型。(type返回的数据类型包括:string(字符串)、hash(哈希)、list(list集合)、set(set集合)、zset(set有序集合)以及none(当key不存在时返回))。
(10)以上常用命令的复杂度:
keys | O(n) |
dbsize | O(1) |
del | O(1) |
exists | O(1) |
expire | O(1) |
ttl | O(1) |
persist | O(1) |
type | O(1) |
二、数据结构和内部编码
redis对外的数据类型为String、hash、list、set和zset,但是对于redis内部来说,采用的却是其他的类型来实现的,具体如下图所示(因为redis是使用内存来存储数据的,而内存的资源也是非常昂贵的,所以,如果我们在实现一种数据结构的时候元素比较多的情况下可以用空间来换取时间,就可以使用压缩的数据结构,例如以ziplist来来实现hash,反过来元素比较少的情况下可以用时间来换取空间的话,就可以使用hashtable来实现hash):
其实在redis源码的内部,存在一个redisObject的对象或者说是结构体,它的具体结构如下图所示:
三、单线程
redis在一个瞬间只会执行一条命令,其他的命令要等前面的命令执行完成才会执行。redis使用单线程模型速度快的最主要原因是因为redis存储数据使用的是内存,其他原因包括redis使用非阻塞IO以及避免线程切换和竞态消耗。
由于redis使用的单线程模型,所以我们在操作的时候需要注意几点,第一是一次只运行一条命令,第二是拒绝长(慢)命令,例如:keys、flushall、flushdb、slow、lua script、mutil/exec、operate big value(collection)。
redis其实不完全是单线程,redis在执行fysnc file descriptor和close file descriptor是单独开了一个线程来执行的。
四、字符串
字符串类型常用与缓存、计数等应用场景。
用于缓存的常用方法:
(1)get key :获得key的值,时间复杂度为O(1)。
(2)set key value :设置一个值为value的key,时间复杂度为O(1)。
(3)del key :删除key,时间复杂度为O(1)。
用于计数的常用方法:
(1)incr key :让key自增1,如果key不存在,则先添加这个key,值从0开始,自增1后返回这个key,key返回结果为1,时间复杂度为O(1)。
(2)decr key :让key自减1,如果key不存在,则先添加这个key,值从0开始,自减1后返回这个key,key返回结果为-1,时间复杂度为O(1)。
(3)incrby key k :让key自增k,如果key不存在,则先添加这个key,值从0开始,自增k后返回这个key,key返回结果为k,时间复杂度为O(1)。
(4)decrby key k :让key自减k,如果key不存在,则先添加这个key,值从0开始,自减k后返回这个key,key返回结果为-k,时间复杂度为O(1)。
其他常用方法:
(1)setnx key value :key不存在,才设置(相当于新增操作),时间复杂度为O(1)。
(2)set key value xx :key存在,才设置(相当于更新操作),时间复杂度为O(1)。
(3)mget key1 key2 key3.... :批量获取key,原子操作,时间复杂度O(n)。
(4)mset key1 value1 key2 value2 key3 value3... :批量设置key-value,时间复杂度O(n)。
(5)getset key newvalue :更新key的值并返回旧的key值,时间复杂度O(1)。
(6)append key value :将value追加到旧的value后,时间复杂度O(1)。
(7)strlen key :返回字符串的长度(注意字符串)。
(8)incrbyfloat key 3.5 :让key自增3.5,如果key不存在,则先添加这个key,值从0开始,自增3.5后返回这个key,key返回结果为3.5,如果想要实现浮点数的自减,则传一个负值即可实现,例如传-3.5。
(9)getrange key start end :获取字符串指定下标所有的值,下标从0开始。
(10)setrange key index value :设置指定下标所对应的值,下标从0开始。
五、哈希
(1)hget key filed :获取hash key中对应的filed的value,时间复杂度是O(1)。
(2)hset key filed value :设置hash key中对应filed的value,时间复杂度是O(1)。
(3)hdel key filed :删除hash key中对应filed的value,时间复杂度是O(1)。
(4)hgetall key :获取hash key中所有的属性和属性对应的值,时间复杂度是O(n)。
(5)hexists key filed :判断hash key中是否有filed,时间复杂度是O(1)。
(6)hlen key :获取hash key中filed的数量,时间复杂度是O(1),不是遍历所有的key来计算数量的。
(7)hmget key filed1 filed2 ... filedN :批量获取hash key的一批filed对应的值,时间复杂度是O(n)。
(8)hmset key filed1 value1 filed2 value2 ... filedN valueN :批量设置hash key的一批filed value,时间复杂度是O(n)。
(9)hvals key :返回hash key对应所有filed的value,时间复杂度是O(n)。
(10)hkeys key :返回hash key对应所有filed,时间复杂度是O(n)。
(11)hincrby key filed intCounter :hash key对应的field的value自增intCount,时间复杂度为O(1)。
(12)hincrbyfloat key filed floatCounter :hash key对应的filed的value自增floatCounter,时间复杂度为O(1)。
(13)hsetnx key filed value :设置hash key对应filed的value,如果field已存在,则设置失败,时间复杂度为O(1)。
六、列表
(1)rpush key value1 value2 ... valueN:从列表右端插入值(1-N),时间复杂度为O(1~N)。
(2)lpush key value1 value2 ... valueN:从列表左端插入值(1-N),时间复杂度为O(1~N)。
(3)linsert key before|after value newValue:在list指定的值前|后插入newValue。
(4)lpop key:从左边弹出一个元素。
(5)rpop key:从右边弹出一个元素。
(6)lrem key count value:根据count的值,从列表中删除所有value相等的项
(a)count > 0,从左到右,删除最多count个value相等的项。
(b)count < 0,从右到左,删除最多Math.abs(count)个value相等的项。
(c)count = 0,删除所有value相等的项。
(7)ltrim key start end:按照索引指定范围修剪列表,列所索引从0开始。时间复杂度为O(N)。
(8)lrang key start end:获取列表指定索引范围所有item(包含end),从左到右索引从0开始,从右到左索引从-1开始。
假如列表有五个元素,那么lrang listkey 0 4:从左边开始获取索引从0开始到4结束的所有值。lrang listkey -1 -5:从右边开始获取索引从-1到-5的所有值。lrang listkey 0 -1:从左边开始获取索引从0开始到-1结束的所有值。
(9)llen key:获取列表长度,不是遍历所有的key来计算数量的,所以时间复杂度是O(1)。
(10)lset key index newValue:设定列表指定索引值为newValue。时间复杂度为O(N)。
(11)blpop key timeout:lpop的阻塞版本,timeout是阻塞超时时间,如果timeout=0则为永远不阻塞,意思也就是死等,直到从左边插入一个新的元素才返回,时间复杂度为O(1)。
(12)brpop key timeout:rpop的阻塞版本,timeout是阻塞超时时间,如果timeout=0则为永远不阻塞,意思也就是死等,直到从右边插入一个新的元素才返回,时间复杂度为O(1)。
(13)列表使用时的一些规则:
(a)如果想要实现一个栈,则可以使用:LPUSH + LPOP命令控制左进左出来实现。
(b)如果想要实现一个队列,则可以使用:LPUSH + RPOP命令控制左进右出来实现。
(c)如果想要实现一个有数量控制的列表,则可以使用:LPUSH + LTRIM命令控制列表的数量来实现。
(d)如果想要实现一个消息队列系统,则可以使用:LPUSH + BRPOP来实现。
七、集合
(1)sadd key element:向集合key中添加element,如果element已经存在,则添加失败,时间复杂度为O(1)。
(2)srem key element:将集合key中的element移除掉,时间复杂度为O(1)。
(3)scard key:计算集合大小
(4)sismember key value:判断value在集合中是否存在,存在返回1。
(5)srandmember key count:从集合中随机挑选count个元素,不会删除这些元素。
(6)spop key:从集合中随机弹出一个元素,会删除这个弹出的元素。
(8)smembers key:获取集合所有的元素,返回结果无序,如果集合中元素比较多的话,容易阻塞redis。
(9)sdiff key1 key2:计算集合1和集合2之间的差集。
(10)sinter key1 key2:计算集合1和集合2之间的交集。
(11)sunion key1 key2:计算集合1和集合2之间的并集。
(12)sdiff |sinter |sunion + store destkey:将差集、交集或者并集的结果保存到destkey中。
八、有序集合
有序集合是通过score(分数)来对element(元素)进行排序的。
(1)zadd key score element(可以是多对):添加score和element ,分数能够重复,但是元素不能重复,时间复杂度为O(logN)。
(2)zrem key element(可以是多个):删除有序集合中的元素,时间复杂度为O(1)。
(3)zscore key element:返回元素的分数。
(4)zincrby key increScore element:增加或减少元素的分数。
(5)zcard key:返回元素中的个数,时间复杂度为O(1)。
(6)zrank key element:返回元素的排名,排名从1开始。
(7)zrange key startindex endindex [-withscores]:获取指定下标的元素,从左到右下标从0开始,从右到做下标从-1开始,如果带了-withscores则在显示元素时也会把元素对应的分数显示出来,时间复杂度为O(log(n)+m),n为集合中元素的个数,m为获取的元素个数。
(8)zrangebyscore key minScore maxScore [-withsocres]:按照指定分数的范围返回元素,时间复杂度为O(log(n)+m),n为集合中元素的个数,m为获取的元素个数。
(9)zcount key minScore maxScored:返回有序集合内在指定分数范围内的个数,时间复杂度为O(log(n)+m),n为集合中元素的个数,m为获取的元素个数。
(10)zremrangebyrank key startindex endindex:删除指定下标中的元素,从左到右下标从0开始,从右到做下标从-1开始,时间复杂度为O(log(n)+m),n为集合中元素的个数,m为删除的元素个数。
(11)zremrangebyscore key minScore maxScore:删除指定分数范围内的元素,时间复杂度为O(log(n)+m),n为集合中元素的个数,m为删除的元素个数。