资源描述
Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,December 19,2008,#,Redis,开源,key-value,存储系统,曲延从,目录索引,Redis,简介,Redis,安装,Redis,配置,Redis,支持的数据类型,Redis,的功能,持久化,(,persistence,),主从复制,(,master-slave replication,),事物支持,(,transaction,),发布订阅,(,pub/sub,),管道,(,pipeline,),虚拟内存,(,vm,),Redis,性能,Redis,部署,Redis,应用场景,Redis,总结,Redis,简介,Redis,是一款开源的、高性能的键,-,值存储(,key-value store,)。它常被称作是一款数据结构服务器(,data structure server,)。,Redis,的键值可以包括字符串(,strings,)类型,同时它还包括哈希(,hashes,)、列表(,lists,)、集合(,sets,)和 有序集合(,sorted sets,)等数据类型。对于这些数据类型,你可以执行原子操作。例如:对字符串进行附加操作(,append,);递增哈希中的值;向列表中增加元素;计算集合的交集、并集与差集等。,为了获得优异的性能,,Redis,采用了内存中(,in-memory,)数据集(,dataset,)的方式。同时,,Redis,支持数据的持久化,你可以每隔一段时间将数据集转存到磁盘上(,snapshot,),或者在日志尾部追加每一条操作命令(,append only file,aof,)。,Redis,简介,Redis,同样支持主从复制(,master-slave replication,),并且具有非常快速的非阻塞首次同步(,non-blocking first synchronization,)、网络断开自动重连等功能。同时,Redis,还具有其它一些特性,其中包括简单的事物支持、发布订阅(,pub/sub,)、管道(,pipeline,)和虚拟内存(,vm,)等。,Redis,具有丰富的客户端,支持现阶段流行的大多数编程语言。,php,常用的是,phpredis,(,redis.io/clients,),Redis,安装,下载最新稳定版,redis-2.2.11,(,redis.io/download,),tar zxvf redis-2.2.11,解压缩,cd src,进入,src,目录,make,编译,Redis,make test,可以测试一下(本步可省略),make install,安装,默认安装目录是,/usr/local/bin,,生成如图,5,个二进制文件,可以将其拷到新建目录下,例如,:/usr/local/redis/bin,Redis,安装,cp,源码,/src/redis.conf /usr/local/redis/etc,配置文件复制,cd/usr/local/redis,./bin/redis-server./etc/redis.conf,启动,Redis,服务,此时,redis,已经运行,但要获得好的性能,还需要对配置文件进行合理的配置,Redis,配置,1.Redis,默认不是以守护进程的方式运行,可以通过该配置项修改,使用,yes,启用守护进程,daemonize no,2.,当,Redis,以守护进程方式运行时,,Redis,默认会把,pid,写入,/var/run/redis.pid,文件,可以通过,pidfile,指定,pidfile/var/run/redis.pid,3.,指定,Redis,监听端口,默认端口为,6379,,作者在自己的一篇博文中解释了为什么选用,6379,作为默认端口,因为,6379,在手机按键上,MERZ,对应的号码,而,MERZ,取自意大利歌女,Alessia Merz,的名字,port 6379,4.,绑定的主机地址,bind 127.0.0.1,5.,当 客户端闲置多长时间后关闭连接,如果指定为,0,,表示关闭该功能,timeout 300,6.,指定日志记录级别,,Redis,总共支持四个级别:,debug,、,verbose,、,notice,、,warning,,默认为,verbose,loglevel verbose,Redis,配置,7.,日志记录方式,默认为标准输出,如果配置,Redis,为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给,/dev/null,logfile stdout,8.,设置数据库的数量,默认数据库为,0,,可以使用,SELECT,命令在连接上指定数据库,id,databases 16,9.,指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合,save ,Redis,默认配置文件中提供了三个条件:,save 900 1,save 300 10,save 60 10000,分别表示,900,秒(,15,分钟)内有,1,个更改,,300,秒(,5,分钟)内有,10,个更改以及,60,秒内有,10000,个更改。,10.,指定存储至本地数据库时是否压缩数据,默认为,yes,,,Redis,采用,LZF,压缩,如果为了节省,CPU,时间,可以关闭该选项,但会导致数据库文件变的巨大,rdbcompression yes,Redis,配置,11.,指定本地数据库文件名,默认值为,dump.rdb,dbfilename dump.rdb,12.,指定本地数据库存放目录,dir./,13.,设置当本机为,slav,服务时,设置,master,服务的,IP,地址及端口,在,Redis,启动时,它会自动从,master,进行数据同步,slaveof ,14.,当,master,服务设置了密码保护时,,slav,服务连接,master,的密码,masterauth,15.,设置,Redis,连接密码,如果配置了连接密码,客户端在连接,Redis,时需要通过,AUTH,命令提供密码,默认关闭,requirepass foobared,16.,设置同一时间最大客户端连接数,默认无限制,,Redis,可以同时打开的客户端连接数为,Redis,进程可以打开的最大文件描述符数,如果设置,maxclients 0,,表示不作限制。当客户端连接数到达限制时,,Redis,会关闭新的连接并向客户端返回,max number of clients reached,错误信息,maxclients 128,Redis,配置,17.,指定,Redis,最大内存限制,,Redis,在启动时会把数据加载到内存中,达到最大内存后,,Redis,会先尝试清除已到期或即将到期的,Key,,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。,Redis,新的,vm,机制,会把,Key,存放内存,,Value,会存放在,swap,区,maxmemory,18.,指定是否在每次更新操作后进行日志记录,,Redis,在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为,redis,本身同步数据文件是按上面,save,条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为,no,appendonly no,19.,指定更新日志文件名,默认为,appendonly.aof,appendfilename appendonly.aof,20.,指定更新日志条件,共有,3,个可选值:,no,:表示等操作系统进行数据缓存同步到磁盘(快),always,:表示每次更新操作后手动调用,fsync(),将数据写到磁盘(慢,安全),everysec,:表示每秒同步一次(折衷,默认值),appendfsync everysec,Redis,配置,21.,指定是否启用虚拟内存机制,默认值为,no,,简单的介绍一下,,VM,机制将数据分页存放,由,Redis,将访问量较少的页即冷数据,swap,到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析,Redis,的,VM,机制),vm-enabled no,22.,虚拟内存文件路径,默认值为,/tmp/redis.swap,,不可多个,Redis,实例共享,vm-swap-file/tmp/redis.swap,23.,将所有大于,vm-max-memory,的数据存入虚拟内存,无论,vm-max-memory,设置多小,所有索引数据都是内存存储的,(Redis,的索引数据 就是,keys),也就是说,当,vm-max-memory,设置为,0,的时候,其实是所有,value,都存在于磁盘。默认值为,0,vm-max-memory 0,24.Redis swap,文件分成了很多的,page,,一个对象可以保存在多个,page,上面,但一个,page,上不能被多个对象共享,,vm-page-size,是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,,page,大小最好设置为,32,或者,64bytes,;如果存储很大大对象,则可以使用更大的,page,,如果不 确定,就使用默认值,vm-page-size 32,25.,设置,swap,文件中的,page,数量,由于页表(一种表示页面空闲或使用的,bitmap,)是在放在内存中的,在磁盘上每,8,个,pages,将消耗,1byte,的内存。,vm-pages 134217728,Redis,配置,26.,设置访问,swap,文件的线程数,最好不要超过机器的核数,如果设置为,0,那么所有对,swap,文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为,4,vm-max-threads 4,27.,设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启,glueoutputbuf yes,28.,指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法,hash-max-zipmap-entries 64,hash-max-zipmap-value 512,29.,指定是否激活重置哈希,默认为开启,activerehashing yes,30.,指定包含其它的配置文件,可以在同一主机上多个,Redis,实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件,include/path/to/local.conf,Redis,支持的数据类型,Keys,非二进制安全的字符类型(,not binary-safe strings,),Values,Strings,(,Binary-safe strings,),Lists,(,Lists of binary-safe strings,),Sets,(,Sets of binary-safe strings,),Sorted sets,(,Sorted sets of binary-safe strings,),Hash,Key,redis,本质上一个,key-value,数据库,所以我们首先来看看他的,key.,首先,key,也是字符串类型,由于,key,不是,binary safe,的字符串,所以像,“my key”,和,“mykeyn”,这样包含空格和换行的,key,是不允许的。,我们在使用的时候可以自己定义一个,Key,的格式。例如,object-type:id:field,Key,不要太长。占内存,查询慢。,Key,不要太短。,u:1000:pwd,不如,user:1000:password,可读性好,Key,相关命令,exits,key,测试指定,key,是否存在,返回,1,表示存在,,0,不存在,del,key1 key2.keyN,删除给定,key,返回删除,key,的数目,,0,表示给定,key,都不存在,type,key,返回给定,key,的,value,类型。返回,none,表示不存在,,key,有,string,字符类型,,list,链表类型,set,无序集合类型等,.,keys,pattern,返回匹配指定模式的所有,key,(支持*,?,,abc,的方式),下面给个例子,Key,相关命令,randomkey,返回从当前数据库中随机选择的一个,key,如果当前数据库是空的,返回空串,rename,oldkey newkey,原子的重命名一个,key,如果,newkey,存在,将会被覆盖,返回,1,表示成功,,0,失败。失败可能是,oldkey,不存在或者和,newkey,相同,renamenx,oldkey newkey,同上,但是如果,newkey,存在返回失败,dbsize,返回当前数据库的,key,数量,expire,key seconds,为,key,指定过期时间,单位是秒。返回,1,成功,,0,表示,key,已经设置过过期时间或者不存在,ttl,key,返回设置了过期时间的,key,的剩余过期秒数,,-1,表示,key,不存在或者没有设置过过期时间,select,db-index,通过索引选择数据库,默认连接的数据库所有是,0,默认数据库数是,16,个。返回,1,表示成功,,0,失败,move,key db-index,将,key,从当前数据库移动到指定数据库。返回,1,成功。,0,如果,key,不存在,或者已经在指定数据库中,flushdb,删除当前数据库中所有,key,此方法不会失败。慎用,flushall,删除所有数据库中的所有,key,,此方法不会失败。更加慎用,String,string,是,redis,最基本的类型,而且,string,类型是二进制安全的。,redis,的,string,可以包含任何数据。包括,jpg,图片或者序列化的对象。,最大上限是,1G,字节。,如果只用,string,类型,,redis,就可以被看作加上持久化特性的,memcached,String,相关命令,set,key value,设置,key,对应的值为,string,类型的,value,返回,1,表示成功,,0,失败,setnx,key value,同上,如果,key,已经存在,返回,0,。,nx,是,not exist,的意思,get,key,获取,key,对应的,string,值,如果,key,不存在返回,nil,getset,key value,设置,key,的值,并返回,key,的旧值。如果,key,不存在返回,nil,mget,key1 key2.keyN,一次获取多个,key,的值,如果对应,key,不存在,则对应返回,nil,。下面是个实验,nonexisting,不存在,对应返回,nil,String,相关命令,mset,key1 value1.keyN valueN,一次设置多个,key,的值,成功返回,1,表示所有的值都设置了,失败返回,0,表示没有任何值被设置,msetnx,key1 value1.keyN valueN,同上,但是不会覆盖已经存在的,key,incr,key,对,key,的值做加加操作,并返回新的值。注意,incr,一个不是,int,的,value,会返回错误,,incr,一个不存在的,key,,则设置,key,为,1,decr,key,同上,但是做的是减减操作,,decr,一个不存在,key,,则设置,key,为,-1,incrby,key integer,同,incr,,加指定值,,key,不存在时候会设置,key,,并认为原来的,value,是,0,decrby,key integer,同,decr,,减指定值。,decrby,完全是为了可读性,我们完全可以通过,incrby,一个负值来实现同样效果,反之一样。,String,相关命令,append,key value,给指定,key,的字符串值追加,value,返回新字符串值的长度。下面给个例子,substr,key start end,返回截取过的,key,的字符串值,注意并不修改,key,的值。下标是从,0,开始的。,List,redis,的,list,类型其实就是一个每个子元素都是,string,类型的双向链表。我们可以通过,push,pop,操作从链表的头部或者尾部添加删除元素。这使得,list,既可以用作栈,也可以用作队列。,list,的,pop,操作还有阻塞版本的。当我们,lrpop,一个,list,对象是,如果,list,是空,或者不存在,会立即返回,nil,。但是阻塞版本的,blrpop,可以则可以阻塞,当然可以加超时时间,超时后也会返回,nil,。为什么要阻塞版本的,pop,呢,主要是为了避免轮询。举个简单的例子如果我们用,list,来实现一个工作队列。执行任务的,thread,可以调用阻塞版本的,pop,去获取任务这样就可以避免轮询去检查是否有任务存在。当任务来时候工作线程可以立即返回,也可以避免轮询带来的延迟。,List,相关命令,lpush,key string,在,key,对应,list,的头部添加字符串元素,返回,1,表示成功,,0,表示,key,存在且不是,list,类型,rpush,key string,同上,在尾部添加,llen,key,返回,key,对应,list,的长度,,key,不存在返回,0,如果,key,对应类型不是,list,返回错误,lrange,key start end,返回指定区间内的元素,下标从,0,开始,负值表示从后面计算,,-1,表示倒数第一个元素,,key,不存在返回空列表,ltrim,key start end,截取,list,,保留指定区间内元素,成功返回,1,,,key,不存在返回错误,lset,key index value,设置,list,中指定下标的元素值,成功返回,1,,,key,或者下标不存在返回错误,lrem,key count value,从,key,对应,list,中删除,count,个和,value,相同的元素。,count,为,0,时候删除全部,lpop,key,从,list,的头部删除元素,并返回删除元素。如果,key,对应,list,不存在或者是空返回,nil,,如果,key,对应值不是,list,返回错误,List,相关命令,rpop,同上,但是从尾部删除,blpop,key1.keyN timeout,从左到右扫描返回对第一个非空,list,进行,lpop,操作并返回,比如,blpop list1 list2 list3 0,如果,list,不存在,,list2,list3,都是非空则对,list2,做,lpop,并返回从,list2,中删除的元素。如果所有的,list,都是空或不存在,则会阻塞,timeout,秒,,timeout,为,0,表示一直阻塞。当阻塞时,如果有,client,对,key1.keyN,中的任意,key,进行,push,操作,则第一在这个,key,上被阻塞的,client,会立即返回。如果超时发生,则返回,nil,。,brpop,同,blpop,,一个是从头部删除一个是从尾部删除,rpoplpush,srckey destkey,从,srckey,对应,list,的尾部移除元素并添加到,destkey,对应,list,的头部,最后返回被移除的元素值,整个操作是原子的,.,如果,srckey,是空或者不存在返回,nil,Set,redis,的,set,是,string,类型的无序集合。,set,元素最大可以包含,(2,的,32,次方,-1),个元素。,set,的是通过,hash table,实现的,,hash table,会随着添加或者删除自动的调整大小,关于,set,集合类型除了基本的添加删除操作,其他有用的操作还包含集合的取并集,(union),,交集,(intersection),,差集,(difference),。通过这些操作可以很容易的实现,sns,中的好友推荐和,blog,的,tag,功能。,Set,相关命令,sadd,key member,添加一个,string,元素到,key,对应的,set,集合中,成功返回,1,如果元素以及在集合中返回,0,key,对应的,set,不存在返回错误,srem,key member,从,key,对应,set,中移除给定元素,成功返回,1,,如果,member,在集合中不存在或者,key,不存在返回,0,,如果,key,对应的不是,set,类型的值返回错误,spop,key,删除并返回,key,对应,set,中随机的一个元素,如果,set,是空或者,key,不存在返回,nil,srandmember,key,同,spop,,随机取,set,中的一个元素,但是不删除元素,smove,srckey dstkey member,从,srckey,对应,set,中移除,member,并添加到,dstkey,对应,set,中,整个操作是原子的。成功返回,1,如果,member,在,srckey,中不存在返回,0,,如果,key,不是,set,类型返回错误,scard,key,返回,set,的元素个数,如果,set,是空或者,key,不存在返回,0,sismember,key member,判断,member,是否在,set,中,存在返回,1,,,0,表示不存在或者,key,不存在,sinter,key1 key2.keyN,返回所有给定,key,的交集,sinterstore,dstkey key1.keyN,同,sinter,,但是会同时将交集存到,dstkey,下,Set,相关命令,sunion,key1 key2.keyN,返回所有给定,key,的并集,sunionstore,dstkey key1.keyN,同,sunion,,并同时保存并集到,dstkey,下,sdiff,key1 key2.keyN,返回所有给定,key,的差集,sdiffstore,dstkey key1.keyN,同,sdiff,,并同时保存差集到,dstkey,下,smembers,key,返回,key,对应,set,的所有元素,结果是无序的,Sorted set,和,set,一样,sorted set,也是,string,类型元素的集合,不同的是每个元素都会关联一个,double,类型的,score,。,sorted set,的实现是,skip list,和,hash table,的混合体。当元素被添加到集合中时,一个元素到,score,的映射被添加到,hash table,中,另一个,score,到元素的映射被添加到,skip list,并按照,score,排序,所以就可以有序的获取集合中的元素。,Sorted set,相关命令,zadd,key score member,添加元素到集合,元素在集合中存在则更新对应,score,zrem,key member,删除指定元素,,1,表示成功,如果元素不存在返回,0,zincrby,key incr member,增加对应,member,的,score,值,然后移动元素并保持,skip list,有序。返回更新后的,score,值,zrank,key member,返回指定元素在集合中的排名(下标,非,score,),集合中元素是按,score,从小到大排序的,zrevrank,key member,同上,但是集合中元素是按,score,从大到小排序,zrange,key start end,类似,lrange,操作从集合中取指定区间的元素。返回的是有序结果,zrevrange,key start end,同上,返回结果是按,score,逆序的,zrangebyscore,key min max,返回集合中,score,在给定区间的元素,zcount,key min max,返回集合中,score,在给定区间的数量,zcard,key,返回集合中元素个数,zscore,key element,返回给定元素对应的,score,zremrangebyrank,key min max,删除集合中排名在给定区间的元素,zremrangebyscore,key min max,删除集合中,score,在给定区间的元素,Hash,redis hash,是一个,string,类型的,field,和,value,的映射表。,hash,特别适合用于存储对象。相较于将对象的每个字段存成单个,string,类型。将一个对象存储在,hash,类型中会占用更少的内存,并且可以更方便的存取整个对象。,Hash,相关命令,hset,key field value,设置,hash field,为指定值,如果,key,不存在,则先创建,hget,key field,获取指定的,hash field,hmget,key filed1.fieldN,获取全部指定的,hash filed,hmset,key filed1 value1.filedN valueN,同时设置,hash,的多个,field,hincrby,key field integer,将指定的,hash filed,加上给定值,hexists,key field,测试指定,field,是否存在,hdel,key field,删除指定的,hash field,hlen,key,返回指定,hash,的,field,数量,hkeys,key,返回,hash,的所有,field,hvals,key,返回,hash,的所有,value,hgetall,返回,hash,的所有,filed,和,value,持久化,redis,是一个支持持久化的内存数据库,也就是说,redis,需要经常将内存中的数据同步到磁盘来保证持久化,这是相对,memcache,来说的一个大的优势。,redis,支持两种持久化方式,一种是,Snapshotting,(快照)也是默认方式,另一种是,Append-only file,(缩写,aof,)的方式。,Snapshotting,快照是默认的持久化方式。这种方式将内存中数据以快照的方式写入到二进制文件中,默认的文件名为,dump.rdb,。可以配置自动做快照持久 化的方式。我们可以配置,redis,在,n,秒内如果超过,m,个,key,被修改就自动做快照,下面是默认的快照保存配置,save 900 1,#900,秒内如果超过,1,个,key,被修改,则发起快照保存,save 300 10,#300,秒内容如超过,10,个,key,被修改,则发起快照保存,save 60 10000,持久化,Append-only file,aof,比快照方式有更好的持久化性,是由于在使用,aof,持久化方式时,redis,会将每一个收到的写命令都通过,write,函数追加到文件中,(,默认是,appendonly.aof),。当,redis,重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于,os,会在内核中缓存,write,做的修改,所以可能不是立即写到磁盘上。这样,aof,方式的持久化也还是有可能会丢失部分修改。不过我们可以通过配置文件告诉,redis,我们想要 通过,fsync,函数强制,os,写入到磁盘的时机。有三种方式如下(默认是:每秒,fsync,一次),appendonly,yes,/,启用,aof,持久化方式,#,appendfsync always,/,每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用,appendfsync everysec,/,每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐,#,appendfsync no,/,完全依赖,os,,性能最好,持久化没保证,主从复制,主从复制允许多个,slave server,拥有和,master server,相同的数据库副本。下面是关于,redis,主从复制的一些特点,1.master,可以有多个,slave,2.,除了多个,slave,连到相同的,master,外,,slave,也可以连接其他,slave,形成图状结构,3.,主从复制不会阻塞,master,。也就是说当一个或多个,slave,与,master,进行初次同步数据时,,master,可以继续处理,client,发来的请求。相反,slave,在初次同步数据时则会阻塞,不能处理,client,的请求。,4.,主从复制可以用来提高系统的可伸缩性(我们可以用多个,slave,专门用于,client,的读请求,比如,sort,操作可以使用,slave,来处理),也可以用来做简单的数据冗余。,5.,可以在,master,禁用数据持久化,只需要注释掉,master,配置文件中的所有,save,配置,然后只在,slave,上配置数据持久化。,事物,redis,对事务的支持目前还比较简单。,redis,只能保证一个,client,发起的事务中的命令可以连续的执行,而中间不会插入其他,client,的命令。,Multi,事物开始,Exec,执行事务,Discard,放弃事物,Watch,监听,key,Unwatch,放弃所有,key,的监听,watch,命令会监视给定的,key,当,exec,时候如果监视的,key,从调用,watch,后发生过变化,则整个事务会失败。注意,watch,的,key,是对整个连接有效的,和事务一样,如果连接断开,监视和事务都会被自动清除。,事物演示,发布订阅(,pub/sub,),发布订阅,(pub/sub),是一种消息通信模式。订阅者可以通过,subscribe,和,psubscribe,命令向,redis server,订阅自己感兴趣的消息类型,,redis,将消息类型称为通道,(channel),。当发布者通过,publish,命令向,redis server,发送特定类型的消息时。订阅该消息类型的全部,client,都会收到此消息。这里消息的传递是多对多的。一个,client,可以订阅多个,channel,也可以向多个,channel,发送消息。,Subscribe,Unsubscribe,Psubscribe,Punsubscribe,Publish,发布订阅(,pub/sub,)演示,客户端,1,客户端,2,客户端,3,发布订阅(,pub/sub,)演示,客户端,1,客户端,2,客户端,3,管道(,pipeline,),redis,是一个,cs,模式的,tcp server,,使用和,http,类似的请求响应协议。一个,client,可以通过一个,socket,连接发起多个请求命令。每个请求命令发出后,client,通常 会阻塞并等待,redis,服务处理,,redis,处理完后请求命令后会将结果通过响应报文返回给,client,。基本的通信过程如下,Client:INCR XServer:1Client:INCR XServer:2Client:INCR XServer:3Client:INCR XServer:4,基本上四个命令需要,8,个,tcp,报文才能完成。由于通信会有网络延迟,假如从,client,和,server,之间的包传输时间需要,0.125,秒。那么上面的四个命令,8,个报文至少会需要,1,秒才能完成。,管道(,pipeline,),利用,pipeline,的方式从,client,打包多条命令一起发出,不需要等待单条命令的响应返回,而,redis,服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。通信过程如下,Client:INCR XClient:INCR XClient:INCR XClient:INCR XServer:1Server:2Server:3Server:4,虚拟内存(,vm,)(作者已放弃),redis,没有使用,os,提供的虚拟内存机制而是自己实现了自己的虚拟内存机制,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出内存空间用于其他需要访问的数据。尤其是对于,redis,这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个,redis server,外。另外的能够提高数据库容量的办法就是使用,vm,把那些不经常访问的数据交换的磁盘上。如果我们的存储的数据总是有少部分数据被经常访问,大 部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃。当少量数据被经常访问时,使用,vm,不但能提高单台,redis server,数据库的容量,而且也不会对性能造成太多影响。,vm-enabled yes#,开启,vm,功能,vm-swap-file/tmp/redis.swap#,交换的,value,保存的文件路径,/tmp/redis.swap,vm-max-memory 1000000#,最大内存上限,超过后开始交换,value,到磁盘文件,vm-page-size 32#,每个页面的大小,32,个字节,vm-pages 134217728#,最多使用在文件中使用多少页面,vm-max-threads 4#,用于执行,value,对象换入换出的工作线程数量,,0,表示不使用工作线程,redis,性能,Redis,部署,Redis(Slave),Redis(Master),Applications,mysql,write,replication,read,redis,应用场景,1.,取最新,N,个数据的操作,比如典型的取你网站的最新文章,通过下面方式,我们可以将最新的,5000,条评论的,ID,放在,Redis,的,List,集合中,并将超出集合部分从数据库获取,使用,LPUSH ments,命令,向,list,集合中插入数据,插入完成后再用,LTRIM ments 0 5000,命令使其永远只保存最近,5000,个,ID,然后我们在客户端获取某一页评论时可以用下面的逻辑(伪代码),FUNCTION get_latest_comments(start,num_items):,id_list=redis.lrange(ments,start,start+num_items-1),IF id_list.length num_items,id_list=SQL_DB(SELECT.ORDER BY time LIMIT.),END,RETURN id_list,END,如果你还有不同的筛选维度,比如某个分类的最新,N,条,那么你可以再建一个按此分类的,List,,只存,ID,的话,,Redis,是非常高效的。,redis,应用场景,2.,排行榜应用,取,TOP N,操作,这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,这时候就需要我们的,sorted,set,出马了,将你要排序的值设置成,sorted,set,的,score,,将具体的数据设置成相应的,value,,每次只需要执行一条,ZADD,命令即可。,3.,需要精准设定过期时间的应用,比如你可以把上面说到的,sorted set,的,score,值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序,定时清除过期数据了,不仅是清除,Redis,中的过期数据,你完全可以把,Redis,里这个过期时间当成是对数据库中数据的索引,用,Redis,来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录。,4.,计数器应用,Redis,的命令都是原子性的,你可以轻松地利用,INCR,,,DECR,命令来构建计数器系统。,redis,应用场景,5.Uniq,操作,获取某段时间所有数据排重值,这个使用,Redis,的,set,数据结构最合
展开阅读全文