配色: 字号:
Redis中文入门手册
2017-03-31 | 阅:  转:  |  分享 
  
1

Redis中文入门手册1.0

中国海事服务网(w.cns.com.cn)zhangli收集整理

2

目录1)Redis简介........................................32)数据类型.........................................32.1Redis的Key.....................................32.1..key相关指令介绍...............................3

2.Redis的vaule...................................32..1.string类型...................................32.2.hash类型....................................42.3.list类型....................................52.4.set类型....................................52.5.sortedset类型................................6

3)持久化...........................................73.1快照方式:(默认持久化方式)..........................73.2日志追加方式:...................................74)虚拟内存(适用于value比key大的情况).....................84.1Redis虚拟内存简介................................84.2Redis虚拟内存相关配置..............................8

4.3redis虚拟内存工作方式简介...........................94.31.当vm-ax-threads设为0时(阻塞方式).................94.32.当vm-ax-threads大于0时(工作线程方式)...............95)主从同步.........................................95.1Redis主从复制简介................................95.2Redis主从复制的过程介绍............................10

附录A:redis的安装与配置...................................101.安装.........................................101.1.编译安装...................................101.2.配置......................................11.3.启动redis..................................11.4.关闭redis..................................1

1.5.更新安装redis................................121.6.redis系统管理相关指令简介........................12附录B:安装phredis模块...................................12参考资料与知识扩展.......................................13

3

1)Redis简介Redis是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库。2)数据类型

2.1.Redis的KeyRedis的key是字符串类型,但是key中不能包括边界字符,由于key不是binarysafe的字符串,所以像"mykey"和"mykey\n"这样包含空格和换行的key是不允许的。

2.1.key相关指令介绍exitskey检测指定key是否存在,返回1表示存在,0不存在delkey1key2..keyN删除给定key,返回删除key的数目,0表示给定key都不存在typeky返回给定key值的类型。返回noe表示key不存在,string字符类型,list链表

类型set无序集合类型..keyspatern返回匹配指定模式的所有keyrandomkey返回从当前数据库中随机选择的一个key,如果当前数据库是空的,返回空串reaeoldkeynewkey重命名一个key,如果newkey存在,将会被覆盖,返回1表示成功,0失败。可能是oldkey不存在或者和newkey相同。renamenxoldkeynewkey同上,但是如果newkey存在返回失败。

expirekyseconds为key指定过期时间,单位是秒。返回1成功,0表示key已经设置过过期时间或者不存在。tlkey返回设置过过期时间key的剩余过期秒数。-1表示key不存在或者未设置过期时间。selctdb-index通过索引选择数据库,默认连接的数据库是0,默认数据库数是16个。返回1表示成功,0失败。movekydb-index将key从当前数据库移动到指定数据库。返回1表示成功。0表示key

不存在或者已经在指定数据库中。2.2.Redis的vauleredis提供五种数据类型:string,hash,list,set及sortedset。

2.1.string类型string是最基本的类型,而且string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象。从内部实现来看其实string可以看作byte

4

数组,最大上限是1G字节。string类型数据操作指令简介setkeyvalue设置key对应string类型的值,返回1表示成功,0失败。setnxkeyvalue如果key不存在,设置key对应string类型的值。如果key已经存在,返回0。

getkey获取key对应的string值,如果key不存在返回nilgetstkeyvalue先获取key的值,再设置key的值。如果key不存在返回nil。mgetkey1key2..keyN一次获取多个key的值,如果对应key不存在,则对应返回nil。setkey1value1..keyvalueN一次设置多个key的值,成功返回1表示所有的值都设置了,失败返回0表示没有任何值被设置。msetnxkey1value1..keyNvalueN一次设置多个key的值,但是不会覆盖已经存在的key

incrkey对key的值做+操作,并返回新的值。注意incr一个不是int的value会返回错误,incr一个不存在的key,则设置key值为1。decrkey对key的值做-操作,decr一个不存在key,则设置key值为-1。incrbykeyintegr对key加上指定值,key不存在时候会设置key,并认为原来的value是0。decrbykeyintegr对key减去指定值。decrby完全是为了可读性,我们完全可以通过incrby

一个负值来实现同样效果,反之一样。2.2.hash类型hash是一个string类型的field和value的映射表。添加,删除操作都是O(1)(平均)。

hash特别适合用于存储对象。相对于将对象的每个字段存成单个string类型。将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。省内存的原因是新建一个hash对象时开始是用zipma(又称为smalhas)来存储的。这个zipma其实并不是hashtable,但是zipmap相比正常的hash实现可以节省不少hash本身需要的一些元数据存储开销。尽管zipmap的添加,删除,查找都是O(n),但是由于一般对象的field数量都不太多。所以使用zipmap也是很快的,也就是说添加删除平均还是O(1)。如果field

或者value的大小超出一定限制后,redis会在内部自动将zipmap替换成正常的hash实现.这个限制可以在配置文件中指定。has-max-zipma-entries64#配置字段最多64个has-max-zipma-value512#配置value最大为512字节hash类型数据操作指令简介

setkeyfieldvalue设置hashfield为指定值,如果key不存在,则创建hgetkeyfield获取指定的hashfield。mgetkeyfiled1..fieldN获取全部指定的hashfiled。hsetkeyfiled1value1..filedNvalueN同时设置hash的多个field。incrbykeyfieldintegr将指定的hashfiled加上指定值。成功返回hashfiled变更后的值。

hexistkeyfield检测指定field是否存在。delkeyfield删除指定的hashfield。hlenkey返回指定hash的field数量。

5

hkeyskey返回hash的所有field。valskey返回hash的所有value。hgetal返回hash的所有filed和value

2.3.list类型list是一个链表结构,可以理解为一个每个子元素都是string类型的双向链表。主要功能是push、po、获取一个范围的所有值等。操作中key理解为链表的名字。

List类型数据操作指令简介lpushkeystring在key对应list的头部添加字符串元素,返回1表示成功,0表示key存在且不是list类型。rpushkeystring在key对应list的尾部添加字符串元素。lenkey返回key对应list的长度,如果key不存在返回0,如果key对应类型不是list返回错误。

lrangekystartend返回指定区间内的元素,下标从0开始,负值表示从后面计算,-1表示倒数第一个元素,key不存在返回空列表。ltrimkeystartend截取list指定区间内元素,成功返回1,key不存在返回错误。lsetkeyindexvalue设置list中指定下标的元素值,成功返回1,key或者下标不存在返回错误。lremkeycountvalue从List的头部(count正数)或尾部(count负数)删除一定数量(count)

匹配value的元素,返回删除的元素数量。count为0时候删除全部。lpokey从list的头部删除并返回删除元素。如果key对应list不存在或者是空返回nil,如果key对应值不是list返回错误。rpokey从list的尾部删除并返回删除元素。blokey1..keyNtimeout从左到右扫描,返回对第一个非空list进行lpo操作并返回,比如blpolist1list2list30,如果list不存在list2,list3都是非空则对list2做

lpo并返回从list2中删除的元素。如果所有的list都是空或不存在,则会阻塞timeout秒,timeout为0表示一直阻塞。当阻塞时,如果有client对key1.keyN中的任意key进行push操作,则第一在这个key上被阻塞的client会立即返回。如果超时发生,则返回nil。有点像unix的selct或者pol。brpo同blpo,一个是从头部删除一个是从尾部删除。

2.4.set类型set是无序集合,最大可以包含(2的32次方-1)个元素。set的是通过hastable实现的,所以添加,删除,查找的复杂度都是O(1)。hastable会随着添加或者删除自动的调整大小。需要注意的是调整hastable大小时候需要同步(获取写锁)会阻塞其他读写操作。可能不

久后就会改用跳表(skiplist)来实现。跳表已经在sortedsets中使用了。关于set集合类型除了基本的添加删除操作,其它有用的操作还包含集合的取并集(unio),交集(intersction),差集(difernce)。通过这些操作可以很容易的实现SN中的好友推荐和blog的tag功能。

6

set类型数据操作指令简介sadkeymmber添加一个string元素到key对应set集合中,成功返回1,如果元素以及在集合中则返回0,key对应的set不存在则返回错误。sremkeymembr从key对应set中移除指定元素,成功返回1,如果meber在集合中不存在或者key不存在返回0,如果key对应的不是set类型的值返回错误。spokey删除并返回key对应set中随机的一个元素,如果set是空或者key不存在返回

nil。sradmeberkey同spo,随机取set中的一个元素,但是不删除元素。sovesrckeydstkeymmber从srckey对应set中移除meber并添加到dstkey对应set中,整个操作是原子的。成功返回1,如果meber在srckey中不存在返回0,如果key不是set类型返回错误。scardkey返回set的元素个数,如果set是空或者key不存在返回0。

simeberkeymmber判断meber是否在set中,存在返回1,0表示不存在或者key不存在。sinterkey1key2……keyN返回所有给定key的交集。siterstoredstkeykey1...keyN返回所有给定key的交集,并保存交集存到dstkey下。suniokey1key2..keyN返回所有给定key的并集。siostoredstkeykey1..keyN返回所有给定key的并集,并保存并集到dstkey下。

sdifkey1key2..keyN返回所有给定key的差集。sifstoredstkeykey1..keyN返回所有给定key的差集,并保存差集到dstkey下。smeberskey返回key对应set的所有元素,结果是无序的。

2.5.sortedset类型sortedset是有序集合,它在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,会自动重新按新的值调整顺序。可以理解了有两列的mysql表,一列存value,一列存顺序。操作中key理解为sortedset的名字。

SortedSet类型数据操作指令简介adkeyscoremmber添加元素到集合,元素在集合中存在则更新对应score。zremkeymmber删除指定元素,1表示成功,如果元素不存在返回0。zincrbykeyincrmembr增加对应membr的score值,然后移动元素并保持skiplist保持有序。返回更新后的score值。zrankeymmber返回指定元素在集合中的排名(下标),集合中元素是按score从小到大

排序的。zrevrankeymmber同上,但是集合中元素是按score从大到小排序。zragekystartend类似lrange操作从集合中去指定区间的元素。返回的是有序结果zrevrangekystartend同上,返回结果是按score逆序的。zragebyscorekyminmax返回集合中score在给定区间的元素。zcountkeyminmax返回集合中score在给定区间的数量。

zcardkey返回集合中元素个数。zscorekyelmnt返回给定元素对应的score。

7

zremrangebyrankeyminmax删除集合中排名在给定区间的元素。zrerageyscorekyminmax删除集合中score在给定区间的元素3)持久化

通常Redis将数据存储在内存中或虚拟内存中,它是通过以下两种方式实现对数据的持久化。3.1.快照方式:(默认持久化方式)这种方式就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为

dump.rdb。客户端也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有客户端的请求,这种方式会阻塞所有客户端请求。所以不推荐使用。另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步增量数据。如果数据量大的话,写操作会比较多,必然会引起大量的磁盘IO操作,可能会严重影响性能。

注意:由于快照方式是在一定间隔时间做一次的,所以如果redis意外当机的话,就会丢失最后一次快照后的所有数据修改。3.2.日志追加方式:这种方式redis会将每一个收到的写命令都通过write函数追加到文件中(默认

apendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于操作系统会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样的持久化还是有可能会丢失部分修改。不过我们可以通过配置文件告诉redis我们想要通过fsync函数强制操作系统写入到磁盘的时机。有三种方式如下(默认是:每秒fsync一次)

apendonlyes/启用日志追加持久化方式#apendfsyncalways/每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用apendfsyncevrysec/每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐#apendfsynco/完全依赖操作系统,性能最好,持久化没保证

日志追加方式同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incrtest命令10次,文件中必须保存全部10条命令,其实有9条都是多余的。因为要恢复数据库状态其实文件中保存一条setest10就够了。为了压缩这种持久化方式的日志文件。redis提供了bgrewriteaof命令。收到此命令redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的持久化日志文件。

8

4)虚拟内存(适用于value比key大的情况)4.1.Redis虚拟内存简介首先说明下redis的虚拟内存与操作系统虚拟内存不是一码事,但是思路和目的都是相

同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间。对于redis这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个redis服务器以外。另外的能够提高数据库容量的办法就是使用虚拟内存技术把那些不经常访问的数据交换到磁盘上。如果我们存储的数据总是有少部分数据被经常访问,大部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃。当少量数据被经常访问时,使用虚拟内存不但能提高单台redis数据库服务器的容量,而且也不会对性能造成太多影响。

redis没有使用操作系统提供的虚拟内存机制而是自己在用户态实现了自己的虚拟内存机制。主要的理由有以下两点:1.操作系统的虚拟内存是以4k/页为最小单位进行交换的。而redis的大多数对象都远小于4k,所以一个操作系统页上可能有多个redis对象。另外redis的集合对象类型如list,set可能存在于多个操作系统页上。最终可能造成只有10%的key被经常访问,但

是所有操作系统页都会被操作系统认为是活跃的,这样只有内存真正耗尽时操作系统才会进行页的交换。2.相比操作系统的交换方式。redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息。一般压缩后的对象会比内存中的对象小10倍。这样redis的虚拟内存会比操作系统的虚拟内存少做很多IO操作。

4.2.Redis虚拟内存相关配置vm-enabledyes#开启虚拟内存功能vm-swap-file/tmp/redis.wap#交换出来value保存的文件路径/tmp/redis.wapvm-ax-meory26843546#redis使用的最大内存上限(256MB),超过上限后redis开始交换value到磁盘swap文件中。建议设置为系统空闲内存的60%-80%

vm-page-size32#每个redis页的大小32个字节vm-pages13421728#最多在文件中使用多少个页,交换文件的大小=(vm-page-sizevm-pages)4GBvm-ax-threads8#用于执行value对象换入换出的工作线程数量。0表示不使用工作线程(详情后面介绍)redis的虚拟内存在设计上为了保证key的查询速度,只会将value交换到swap文件

中。如果是由于太多key很小的value造成的内存问题,那么redis的虚拟内存并不能解决问题。和操作系统一样redis也是按页来交换对象的。redis规定同一个页只能保存一个对象。但是一个对象可以保存在多个页中。在redis使用的内存没超过vm-ax-meory之前是不会交换任何value的。当超过最大内存限制后,redis会选择把较老的对象交换到swap文件中去。如果两个对象一样老会优先交换比较大的对象,精确的交换计算公式swapabilty=agelog(size_in_meory)。对于vm-page-size的设置应该根据自己应用

将页的大小设置为可以容纳大多数对象的尺寸。太大了会浪费磁盘空间,太小了会造成交换

9

文件出现过多碎片。对于交换文件中的每个页,redis会在内存中用一个1bit值来对应记录页的空闲状态。所以像上面配置中页数量(vm-pages13421728)会占用16MB内存用来记录页的空闲状态。vm-ax-threads表示用做交换任务的工作线程数量。如果大于0推荐设为服务器的cpu的核心数。如果是0则交换过程在主线程进行。

4.3.redis虚拟内存工作方式简介4.31.当vm-ax-threads设为0时(阻塞方式)换出主线程定期检查发现内存超出最大上限后,会直接以阻塞的方式,将选中的对象保存到swap文件中,并释放对象占用的内存空间,此过程会一直重复直到下面条件满足

1.内存使用降到最大限制以下2.swap文件满了。3.几乎全部的对象都被交换到磁盘了换入当有客户端请求已经被换出的value时,主线程会以阻塞的方式从swap文件中加载对应的

value对象,加载时此时会阻塞所有客户端。然后处理该客户端的请求4.32.当vm-ax-threads大于0时(工作线程方式)换出

当主线程检测到使用内存超过最大上限,会将选中要交换的对象信息放到一个队列中交给工作线程后台处理,主线程会继续处理客户端请求。换入如果有客户端请求的key已经被换出了,主线程会先阻塞发出命令的客户端,然后将加载对象的信息放到一个队列中,让工作线程去加载。加载完毕后工作线程通知主线程。主线程再

执行客户端的命令。这种方式只阻塞请求的value是已经被换出key的客户端。总的来说阻塞方式的性能会好一些,因为不需要线程同步、创建线程和恢复被阻塞的客户端等开销。但是也相应的牺牲了响应性。工作线程方式主线程不会阻塞在磁盘IO上,所以响应性更好。如果我们的应用不太经常发生换入换出,而且也不太在意有点延迟的话推荐使用阻塞方式。

关于redis虚拟内存更详细介绍可以参考下面链接htp:/redis.io/tpics/internals-vm5)主从同步

5.1.Redis主从复制简介

10

Redis支持将数据同步到多台从库上,这种特性对提高读取性能非常有益。1)master可以有多个slave。2)除了多个slave连到相同的master外,slave也可以连接其它slave形成图状结构。3)主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理客户端发来的请求。相反slave在初次同步数据时则会阻塞不能处理客户端的请求。

4)主从复制可以用来提高系统的可伸缩性,我们可以用多个slave专门用于客户端的读请求,比如sort操作可以使用slave来处理。也可以用来做简单的数据冗余。5)可以在master禁用数据持久化,只需要注释掉master配置文件中的所有save配置,然后只在slave上配置数据持久化。5.2.Redis主从复制的过程介绍

当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后,master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从客

户端发送的命令使用相同的协议格式。当master和slave的连接断开时slave可以自动重新建立连接。如果master同时收到多个slave发来的同步连接命令,只会启动一个进程来写数据库镜像,然后发送给所有slave。配置slave服务器很简单,只需要在配置文件中加入如下配置slaveof192.168.1.6379#指定master的ip和端口

附录A:redis的安装与配置1.1.安装1.1.编译安装

$wgethtp:/redis.goglecode.com/files/redis-2..7.tar.gz$tarxzfredis-2..7.tar.gz$cp-redis-2..7/usr/local/redis$cd/usr/local/redis$make$makeinstal#编译好的文件将被复制到/usr/local/bin下

#redis-erver:Redis服务器的daemon启动程序#reis-cli:edis命令行操作工具。当然,你也可以用telnt根据其纯文本协议来操作#redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能$redis-benchmark-n100–c50#模拟同时由50个客户端发送100个SETs/GETs查

1

询#redis-check-aof:更新日志检查#reis-cec-dump:本地数据库检查

1.2.配置修改配置文件,并将其复制到etc目录下viredis.conf$cpredis.conf/etc/redis.conf

配置文件基本说明daemonize:#是否以后台守护进程方式运行pidfile:#pid文件位置port:#监听的端口号timeout:#请求超时时间loglevl:#log信息级别,总共支持四个级别:debug、verbose、notice、warnig,

默认为verboselogfile:#默认为标准输出(stdout),如果配置为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/nuldatbase:#开启数据库的数量。使用“SELCT库ID”方式切换操作各个数据库save:#保存快照的频率,第一个表示多长时间,第二个表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。

rdbcompresion:#保存快照是否使用压缩dbfilename:#数据快照文件名(只是文件名,不包括目录)。默认值为dump.rdbdir:#数据快照的保存目录(这个是目录)requirepas:#设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH命令提供密码,默认关闭。

1.3.启动redis$redis-erver/etc/redis.conf

1.4.关闭redis$redis-clishutdown#关闭指定端口的redis-erver$redis-cli-p6379shutdown

12

1.5.更新安装redis其它同安装,只是最后makeinstal之前需要把正在运行的老版本redis关闭。1.6.redis系统管理相关指令简介

DBSIZE返回当前数据库key的数量。INFOOOO返回当前redis服务器状态和一些统计信息。MOITOROOOOOO实时监听并返回redis服务器接收到的所有请求信息。SHUDOWNHOHOHO把数据同步保存到磁盘上,并关闭redis服务。CONFIGOGOGOGGETGGGparmetr获取一个redis配置参数信息。(个别参数可能无法获取)OIGOGOGOGSparmetrvalue设置一个redis配置参数信息。(个别参数可能无法获取)

CONFIGOGOGOGRETSAT重置INFO命令的统计信息。(重置包括:Keyspace命中数、Keyspace错误数、处理命令数,接收连接数、过期key数)DEBUGGGGOBJECTOOOkey获取一个key的调试信息。GGGGSGFAULGGG制造一次服务器当机。FLUSHDBHHH删除当前数据库中所有key,此方法不会失败。小心慎用HALHHH删除全部数据库中所有key,此方法不会失败。小心慎用

附录B:安装phredis模块htps:/github.com/nicolasf/phredis下载phredis最新版本

解压>cdphredis/usr/local/ph5/bin/phize#这个phize是安装ph模块的>./configure–with-p-config=/usr/local/ph5/bin/ph-configmake>cpmodules/redis.o/usr/local/ph5/etc/redis.o

接下来在ph.in中添加extension=redis.o.重启apcheph代码测试
$reis->coect(‘127.0..1′,6379);$redis-set(‘test’,''heloworld!’);echo$redis->get(‘test’);?>phredis方法说明:

13

htps:/github.com/nicolasf/phredis/blo/master/README.markdown#readme参考资料与知识扩展

Redis指令大全:htp:/redis.io/cmmandsRedis指令在线模拟练习:htp:/try.redis-db.com/

献花(0)
+1
(本文系关平藏书首藏)