key/value介绍
Redis key值是二进制安全的,这意味着可以用任何二进制序列作为key值,从形如“0foo”的简单字符串到一个JPG文件的内容都可以。空字符串也是有效key值。
关于key的几条规则:
太长的键值,例如1024字节的键值,不仅因为消耗内存,而且在数据中查找这类键值的计算成本很高。
太短的键值,如果你要用 u:1000:pwd
来代替user:1000:password
,这没有什么问题,但后者更易阅读,并且由此增加的空间消耗相对于key object和value object本身来说很小.当然,没人阻止您一定要用更短的键值节省一丁点空间。
最好坚持一种模式;。例如:object-type:id:field
就是个不错的注意,像这样user:1000:password
。我喜欢对多单词的字段名中加上一个点,就像这样:comment.1234.renlv_to
key建议:object-type:id:field
长度10-20
value建议:string不要超过2K set sortedset元素不要超过5000
|
|
通用操作
找到全部给定模式的匹配到的key
|
|
randomkey返回随机key
|
|
exists检查key是否存在
|
|
type 查看key类型
|
|
修改key名称
|
|
renamnx rename not exists,当要修改的新名称存在,会用改名后的覆盖存在的那个key
|
|
将当前数据库的 key 移动到给定的数据库db当中
|
|
dbsize返回当前选择的数据库的key数量
|
|
shutdown 同步保存数据到磁盘,并结束Redis进程
语法:shutdown [NOSAVE|SAVE]
|
|
异步操作Redis
bgrewriteaof (异步重写aof日志文件) 作用减少aof文件大小 BGSAVE(异步保存数据到磁盘)
String字符串类型
这是最简单的Redis类型。如果你只用这种类型,Redis就是一个可以持久化的memcached服务器(注:memcache的数据仅保存在内存中,服务器重启后,数据将丢失)。
常规字符串操作
在Redis中,常用set设置一对key/value键值,然后用get来获取字符串的值。value值可以是任何类型的字符串(包括二进制数据),例如你可以在一个键下保存一个jpg图片。但值的长度不能超过1GB。
set:设置一个建的字符串值
语法:set key value [EX seconds] [PX milliseconds] [NX|XX]
|
|
mset:设置多个key value
|
|
setrange:从指定偏移量开始重写字符串的一部分
|
|
append:将值附加到key中
|
|
getrange:Get a substring of the string stored at a key
|
|
String类型可以用来存储数字
虽然字符串是Redis的基本值类型,但你仍然能通过它完成一些有趣的操作。例如:原子递增。
INCR命令将字符串值解析成整型,将其加1,最后将结果保存为新的字符串值,类似的命令有INCRBY, DECR and DECRBYC实际上他们在内部就是同一个命令,只是看上去有点儿不同。
incr是原子操作意味着什么呢?就是说即使多个客户端对同一个key发出INCR命令,也决不会导致竟争的情况.例如如下情况永远不可能发生:「客户端1和客户端2同时读出“10",他们俩都对其加到11,然后将新值设置为11。最终的值一定是12,read-increment-set操作完成时,其他客户端不会在同一时间执行任何命令。
incr:将键的整数值递增1
|
|
decr:将键的整数值递减1
|
|
incrby:将键增加一个指定定量
|
|
incrbyfloat: 将键增加一个指定定量的浮点值
|
|
为key设置新值并且返回原值
对字符串,另一个操作是GETSET命令,行如其名:他为key设置新值并且返回原值。这有什么用处呢?例如:你的系统每当有新用户访问时就用INCR命令操作一个Redis key。你希望每小时对这个信息收集一次。你就可以GETSET这个key并给其赋值0并读取原值。
getset:设置key的字符串值,并返回旧值
|
|
setbit getbit bitcount binop
这是偏移位上的二进制值
|
|
List类型
要说清楚列表数据类型,最好先讲一点儿理论背景,在信息技术界List这个词常常被使用不当.例如"Python Lists"就名不副实(名为Linked Lists),但他们实际上是数组(同样的数据类型在Ruby中叫数组)。
列表就是有序元素的序列:10,20,1,2,3就是一个列表。但用数组实现的List和用Linked List实现的List,在属性方面大不相同。
Redis lists基于Linked Lists实现。这意味着即使在一个list中有数百万个元素,在头部或尾部添加一个元素的操作,其时间复杂度也是常数级别的。用LPUSH命令在十个元素的list头部添加新元素,和在千万元素list头部添加新元素的速度相同。
那么,坏消息是什么?在数组实现的list中利用索引访问元素的速度极快,而同样的操作在linked list实现的list上没有那么快。
Redis Lists用linked list实现的原因是:对于数据库系统来说,至关重要的特性是:能非常快的在很大的列表上添加元素.另一个重要因素是,正如你将要看到的:Redis lists能在常数时何取得常数长度。
创建list并插入数据
LPUSH命令可向list的左边(头部)添加一个新元素,而RPUSH命令可向list的右边(尾部)添加一个新元素。最后LRANGE命令可从list中取出一定范围的元素。
lpush:向list头部插入数据,如果list不存在则自动创建
|
|
llen:查看list列表元素个数
|
|
lrange:查看列表所有元素
|
|
⚠ 注意:RANGE带有两个索引,范围内第一个和最后一个元素。这两个索引都可以负来告知redis从尾部开始计数,因此-1表示最后一个元素,-2表示list中的倒数第二个元素,以此类推。
lindex:返回指定元素在列表中的下标
|
|
linsert在指定元素前后插入数据
|
|
list应用场景
正如你可以从上面的例子中猜到的,list可被用来实现聊天系统。还可以作为不同进程间传递消息的队列。关键是,你可以每次都以原先添加的顺序访问数据。这不需要任何SQL ORDER BY操作,将会非常快,也会很容易扩展到百万级别元素的规模。
例如在评级系统中,比如社会化新闻网站reddit.com,你可以把每个新提交的链接添加到一个list,用LRANGE可简单的对结果分页。
在博客引擎实现中,你可为每篇日志设置一个list,在该list中推入进博客评论,等等。
向Redis list压入ID而不是实际的数据,
在上面的例子里,我们将“对象”(此例中是简单消息)直接压入Redis list,但通常不应这么做,由于对象可能被多次引4:例如在一个lis:中维护其时间顺序,在一个集合中保存它的类别,只要有必要,它还会出现在其他list中,等等。
让我们回到reddit.com的例子,将用户提交的链接(新闻)添加到list中,有更可靠的方法如下所示
|
|
OK我们自增一个key,很容易得到一个独一无二的自增ID,然后通过此ID创建对象入为对象的每个字段设置一个key。最后将新对象的submitted.news lists。
rpop 从尾部删除一个元素 rpush 向尾部插入一个数据 lpop 从头部删除一个元素
删除list内元素
lrem:删除count的绝对值个value后结束 count > 0从头开始删,<0从尾部开始删
|
|
ltrim:剪切key对应的链接,切[start,stop]一段,并把该段重新赋给key
|
|
rpoplpush:将arr尾部的元素弹出到tmp头部
作用:接收返回值,并做业务处理。如果成功,rpop tmp清除任务;如不成功,下次从tmp表里取任务
|
|
set集合
Redis集合是未排序的集合,其元素是二进制安全的字符串。sadd命令可以向集合添加一个新元素。和sets相关的操作也有许多,比如检测某个元素是否存在,以及实现交集,并集,差集等等。
创建并向集合插入新元素
sadd:向集合内添加一个或多个元素
|
|
smembers:查看集合内所有元素
|
|
删除集合中元素
sadd:从集合内删除一个或多个指定元素
|
|
查看集合内元素
sismember:检查集合中是否存在某个元素
|
|
srandmember:返回元素中指定个数的随机元素
语法 srandmember key [count]
|
|
scard返回元素中的个数
|
|
移动集合内元素
smove:将source里的member移动到destination集合中
语法:SMOVE source destination member
|
|
“b”是这个集合的成员,而“b”不是。集合特别适合表现对象之间的关系。例如用Redis集合可以很容易实现标签功能。
下面是一个简单的方案:对每个想加标签的对象,用一个标签ID集合与之关联,并且对每个已有的标签,一组对象ID与之关联。
例如假设我们的新闻ID=1000被加了三个tag 1,2,5就可以设置下面两个集合
|
|
而有些看上去并不简单的操作仍然能使用相应的redis命令轻松实现。例如我们也许想获得一份同时拥有标签1,2,10和27的对象列表。这可以用SINTER命令来做,他可以在不同集合之间取出交集。
tags:1:obj tags:2:obj tags:5:obj tags:27:obj
|
|
集合计算
创建一个集合
|
|
sinter:取出指定集合内的交集
|
|
sinterstore:将多个集合的交集放入另一个集合内
|
|
sunion获得多个集合的并集
|
|
sdiff获得多个集合的差
|
|
有序集合
集合是使用频率很高的数据类型,但是…对许多问题来说他们也有点儿太不讲顺序了;因此Redis1.2引入了有序集合。他和集合非常相似,也是二进制安全的字符串集合,但是这次带有关联的score,以及一个类似lrange的操作可以返回有序元素,此操作只能作用于有序集合,它就是,zrange命令。
基本上有序集合从某种程度上说是SQL世界的索引在Redis中的等价物。例如在上面提到的reddit.com例子中,并祥有提到如何根据用户投票和时间因素将新闻组合生成首页。我们将看到有序集合如何解决这个问题,但最好先从更简单的事情开始,阐明这个高级数据类型是如何工作的.让我们添加几个黑客,并将他们的生日作为"score"。
添加并查看有序集合
添加一个或多个成员到一个集合,如果这个成员存在,则更新其排序分数
语法:ZADD key [NX|XX] [CH] [INCR] score member [score member …]
选项详解
参数 | 解释 |
---|---|
XX | 仅更新已经存在的元素。不要添加元素。 |
NX | 不要更新现有的元素。始终添加新元素。 |
CH | 从添加的新元素的数量修改返回值,改变元素的总数(CH是更改的缩写)。已更改的元素是添加的新元素,已经存在的元素已更新。所以在命令行中指定的具有与过去相同的分数的元素不计算在内。注意:通常,ZADD的返回值仅计算添加的新元素的数量。 |
INCR | 当指定此选项时,ZADD的行为就像ZINCRBY。在此模式下只能指定一个记分元素对。 |
创建一个集合
|
|
查看某个元素在集合内的位置
|
|
对有序集合采说,按生日排序返回这些数据易如反掌,因为他们已经是有序的。有序集合是通过一个dual-ported数据结构实现的,它包含一个精简的有序列表和一个hash table,因此添加一个元素的时间复杂度是O(log(N))。这还行,但当我们需要访问有序的元素时,Redis不必再做任何事情,它已经是有序的了。
对集合的值排序
通过索引查看一个有序集合的范围
|
|
通过指定索引范围查看有序集合列表(倒序)
|
|
查看集合中的元素个数
返回有序集合中元素的个数
|
|
返回min,max包括极值
|
|
查找集合区间的元素
zrangebysocre:返回有序集合key的分数min与max之间的所有元素(等于min或max)。这些元素被认为是从低到高的顺序排列。min和max可以是-inf(无穷)和+inf(正无穷),可以不需要知道的有序集合最高或最低score来获得元素。
获取1950年之前(两个极值也包含)出生的人
|
|
返回1950,1970区间内的值
|
|
使用)返回 1950,2000区间内的值
|
|
使用limit返回指定区间内的值
|
|
zremrangebyscore这个名字虽然不算好,但他却非常有用,还会返回已删除的元素数量。
回到Reddit的例子,现在我们有个基于有序集合的像样方案来生成首页。用一个有序集合来包含最近几天的新闻(用zremrangebyscore不时的删除旧新闻).用一个后台任务从有序集合中获取所有元素,根据用户投票和新闻时间计算score,然后用新闻ID和scores关联生成reddit.home.page有序集合.要显示首页,我们只需闪电般的调用ZRANGE不时的从reddit.home.page有序集合中删除过旧的新闻也是为了让我们的系统总是工作在有限的新闻集合之上。 更新有序集合的scores.
结束这篇指南之前还有最后一个小贴士.有序集合scores可以在任何时候更新。只要用ZADD对有序集合内的元素操作就会更新它的score(和位置),时间复杂度是O(log(N)),因此即使大量更新,有序集合也是合适的。其中N是排序集合中的元素数,M是返回元素的数量。如果M是常数(例如,总是用LIMIT来询问前10个元素),可以考虑O(log=(N))。
计算交并集
计算由numkeys指定个数的key的的交集,并将结果存储在其中destination
|
|
hash
hash能够存储一个key对多个属性的数据 如:user.username user.password
设置key中的域与值
hset:将key中的field域设置为value,如果field域存在则覆盖原value,不存在则添加
|
|
hmset:给key设置多个field域与值
|
|
获得key中的域和值
hget:返回key中一个域的值
|
|
hgetall:返回key中所有域和值
|
|
hmget:返回key中多个值
|
|
hkeys:返回key中的所有域
|
|
hvals:返回key中的所有域的值
|
|
删除key
hdel:删除key中一个或多个域
|
|
查看域信息
hlen:返回key中域的个数
|
|
hexists:查看key中是否存在某个域
|
|
hstrlen:返回key中域的值的长度
|
|
hash的原子操作
hincrby:对域中的值增长value个(单位整型)
语法:hincrby key field increment
|
|
hincrbyfloat:对域中的值增长value(单位浮点型)
|
|
bitMap 可实现用很小的内存实现高效的存储。
HyperLogLog 超小内存唯一值计数。 12k来实现唯一值得计数
GEO 基于地理信息位置定位