标签:boa 问题 不能 反序列化 pre 更新 灵活 特征 分组
速度快
Redis使用标准C编写实现,而且将所有数据加载到内存中,所以速度非常快。官方提供的数据表明,在一个普通的Linux机器上,Redis读写速度分别达到81000/s和110000/s。
数据结构
可以将Redis看做“数据结构服务器”。目前,Redis支持5种数据结构。
持久化
由于所有数据保持在内存中,所以对数据的更新将异步地保存到磁盘上,Redis提供了一些策略来保存数据,比如根据时间或更新次数。数据超过内存,使用swap,保证数据;
memcacache不能持久化,mongo是部分在内存;
自动操作
Redis对不同数据类型的操作是自动的,因此设置或增加key值,从一个集合中增加或删除一个元素都能安全的操作。
支持多种语言
Redis支持多种语言,诸如Ruby,Python, Twisted Python, PHP, Erlang, Tcl, Perl, Lua, Java, Scala, Clojure等。
主-从复制
Redis支持简单而快速的主-从复制。
官方提供了一个数据,Slave在21秒即完成了对Amazon网站10Gkey set的复制。
Sharding
很容易将数据分布到多个Redis实例中,但这主要看该语言是否支持。目前支持Sharding功能的语言只有PHP、Ruby和Scala。
redis 的作者antirez曾笑称其为一个数据结构服务器(data structures server),redis的所有功能就是将数据以其固有的几种结构保存,并提供给用户操作这几种结构的接口。我们可以想象我们在各种语言中的那些固有数据类型及其操作。
Redis的几种使用方式
Redis的七种特性以及适合的应用场景:
Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字。使用Strings类型,完全实现目前 Memcached 的功能,并且效率更高。还可以享受Redis的定时持久化,操作日志及 Replication等功能。除了提供与 Memcached 一样的get、set、incr、decr 等操作外,Redis还提供了下面一些操作:
String是最简单的数据类型,一个key对应一个Value,String是二进制安全的。它可以包含任何数据,图片或者其他序列化后的对象
方法 |
说明 |
特性 |
set |
设置key对应的的值为String类型的value |
|
get |
获取对应key对应的String的值,如果不存在返回nil |
|
setnx |
设置可以为对应的值为String类型的value,如果key存在返回0不覆盖,不存在返回1 |
nx的意思为not exist Set the value of a key, only if the key does not exist |
setex |
置key对应的值为String类型的value,并指定此键值对应的有效期 SETEX key seconds value |
例:setex mykey 10 你好 |
setrange |
设置key的value的子字符串 |
setrange key 位置 替换的内容 如果替换内容没有原value长,则原value剩余的内容将被保留 |
mset |
一次设置多个key的值,成功返回ok,失败返回0,要成功都成功,要不成功全部失败。 |
mset key1 内容一 key2 内容二 |
msetnx |
一次设置多个key的值,成功返回ok,失败返回0,不覆盖已经存在的值,要成功都成功,要失败都失败。 |
|
getset |
设置key的值并返回key的旧值 |
getset key newValuse |
getrange |
获取key对应的value子字符串 |
getrange key 0 5 //获取前6个字符 |
mget |
批量获取 |
mget key1 key2 key3 //没有设置则返回空 |
incr |
对key的值做增加操作,并返回新的值 |
+1 |
incrby |
对可以的value加指定的值, |
key如果不存在会设置key并value为0 incrby key1 5 //对key1的值加5 |
decr |
对key的值做减减操作 |
-1 |
decrby |
对key的值减去指定值 |
|
append |
给指定key的字符串追加value,返回新的字符串长度 |
|
strlen |
取指定key的value值的长度 |
|
在Memcached中,我们经常将一些结构化的信息打包成hashmap,在客户端序列化后存储为一个字符串的值,比如用户的昵称、年龄、性别、积分等,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。
它是一个String类型的field和value的映射表,它的添加和删除都是平均的,hash特别适合用于存储对象,对于将对象存储成字符串而言,hash会占用更少的内存,并且可以更方便的存取整个对象. 它和java的HashMap完全类似
方法 |
说明 |
特性 |
hset |
设置一个hash 的field为指定值,如果key不存在则先创建 |
hset tab ke1 val1 |
hget |
获取某个hash的某个field值 |
hget tab ke1 |
hsetnx |
类似string只是操作的是hash |
|
hmset |
批量设置hash的内容 |
|
hmget |
获取hash表的全部key值 |
Hmget key field1 field2 |
hincrby |
给hash表的某个字段增加值 |
|
hexists |
判断hash表中某个key是否存在 |
|
hlen |
返回hash表中的key数量 |
|
hdel |
删除指定hash表的某个键值对 |
|
hkeys |
返回hash表中所有的key |
|
hvals |
返回hash表中所有的value |
|
hgetall |
获取hash表中所有key和value |
|
Lists 就是链表,略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。Lists的另一个应用就是消息队列,可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作Lists中某一段的api,你可以直接查询,删除Lists中某一段的元素。
Redis的list是每个子元素都是String类型的双向链表,可以通过push和pop操作从列表的头部或者尾部添加或者删除元素,这样List即可以作为栈,也可以作为队列。
方法 |
说明 |
特性 |
lpush |
在key所对应的list头部添加一个元素 |
l的意思是left |
rpush |
在key说对应的list尾部添加一个元素 |
r的意思是right |
lrange |
显示list里面的内容 |
lrange 0 -1 //全部显示 |
linsert |
在key对应的list |
linsert mylist before one myvalue |
lset |
设置list中指定下标元素的值 |
lset mylist index myvalue |
lrem |
从key对应的list中删除n个和value相同的元素,结果返回影响元素的个数,n<0从尾部开始删除,n=0全删除 |
lrem mylist count "value" |
ltrim |
保留指定key范围内的数据,返回ok成功 |
ltrim mylist 0 3 //0-3是保留的范围 |
lpop |
从list的头部删除一个元素,并返回该删除的元素 |
|
rpop |
从list的尾部弹出一个元素,并返回该删除的元素 |
|
rpoplpush |
从第一个list的尾部元素异常元素并添加到第二个list的头部 |
rpoplpush mylistA mylistB |
lindex |
返回list位置的元素 |
lindex mylist 3 |
llen |
返回list中元素的个数 |
llen mylist |
Sets 就是一个集合,集合的概念就是一堆不重复值的组合。利用Redis提供的Sets数据结构,可以存储一些集合性的数据。
案例:
在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。
Set是集合,是String类型的无序集合,set是通过hashtable实现的,概念和数学中个的集合基本类似,可以交集,并集,差集等等,set中的元素是没有顺序的。
方法 |
说明 |
特性 |
sadd |
向名称为key的set中添加元素,返回影响元素的个数,0为失败,1为成功 |
sadd myset value |
smembers |
查看集合中所有的成员 |
smebers myset |
srem |
删除集合的一个元素 |
srem myset two |
spop |
随机返回并删除set中一个元素 |
spop myset |
sdiff |
返回所有set与第一个set的差集 |
sdiff myset1 myset2 |
sdiffstore |
比较差集并且存储到另一个set中,返回1代表成功 |
sdiffstore setstoreSet mySet1 myset2 |
sinter |
返回所有给定集合的交集 |
sinter myset1 mysert2 //1集合和2集合的交集 |
sinterstore |
返回给定集合的交集并存储到另一个集合 |
sinterstore desset myset1 myset2 //存到desset集合中 |
sunion |
返回所有给定集合的并集 |
sunion set1 set2 |
sunionstore |
返回所有的并集并且存储到另一个集合中,返回影响的元素个数 |
sunionstore destSet myset1 myset2 |
smove |
把第一个集合的元素移动到第二个集合中 |
smove myset myset 你好 |
scard |
返回集合中元素的个数 |
scard myset1 |
sismember |
测试某个元素是否在集合中,返回0是不是,大于0是存在 |
sismember mykey1 你好 |
srandmember |
随机返回个集合中的元素 |
srandmemeber myset1 |
和Sets相比,Sorted Sets增加了一个权重参数score,使得集合中的元素能够按score进行有序排列,比如一个存储全班同学成绩的Sorted Sets,其集合value可以是同学的学号,而score就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。
案例:
可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
Zset类型
它是set的一个升级版本,在set的基础上增加了顺序,这一属性在添加修改元素时可以指定,每次指定后,zset会自动按新的值调整顺序。
方法 |
说明 |
特性 |
zadd |
向zset中添加元素member,score 用于排序,如果元素存在,则更新其顺序,返回0代表没添加成功 |
ZADD key score member zadd myset 3 itim |
zrange |
取出集合中的元素 |
zrange myset 0 -1 withscores//显示序号 by index |
zrem |
删除名称为key的zset中的元素member |
zrem myset itim |
zincrby |
修改元素的排序,如果元素不存在则添加该元素,且排序的score值为增加值 |
zincrby myzset score itim |
zrank |
返回元素在集合中的排序位置,就是索引值 |
zrank myzset itim //itim在集合中的位置 |
zrevrank |
返回从大到小的排序索引值,就是逆序位置 |
zrevrangk myzset itim//逆序的位置 |
zrevrange |
返回集合中从大到小排序(降序)的,索引start到end的所有元素 |
zrevrange myzset 0 -1 //逆序后的元素 |
zrangebyscore |
根据排序索引的scores来返回元素 |
zrangebyscore myzset 1 3 withscores// |
zcount |
返回集合中给定区间的数量 |
zcount myzset 2 4 //集合中2-4索引元素的个数 |
zcard |
返回集合中所有元素的个数 |
zcard myzset //返回所有元素的个数 |
zremrangebyrank |
删除集合中排序在给定区间的所有元素(按索引删除) |
zremrangebyrank myzset 2 3 // |
zremrangebyscore |
删除集合中在给定排序区间的元素 (按顺序删除) |
zremrangebyscore myzset 2 5 // |
Pub/Sub 从字面上理解就是发布(Publish)与订阅(Subscribe),在Redis中,你可以设定对某一个key值进行消息发布及消息订阅,当一个key值上进行了消息发布后,所有订阅它的客户端都会收到相应的消息。这一功能最明显的用法就是用作实时消息系统,比如普通的即时聊天,群聊等功能。
案例:
Qlocenter 下发策略
redis的存储分为内存存储、磁盘存储和log文件三部分,配置文件中有三个参数对其进行配置。
l save seconds updates
save配置,指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。
l appendonly yes/no
appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。
l appendfsync no/always/everysec
appendfsync配置,no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次。
redis使用了两种文件格式:全量数据和增量请求。
全量数据格式是把内存中的数据写入磁盘,便于下次读取文件进行加载;
增量请求文件则是把内存中的数据序列化为操作请求,用于读取文件进行replay得到数据,序列化的操作包括SET、RPUSH、SADD、ZADD。
redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化。redis支持两种持久化方式,一种是 Snapshotting(快照)也是默认方式,另一种是Append-only file(缩写aof)的方式。下面分别介绍
Snapshotting(RDB方式)
快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过配置设置自动做快照持久 化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置
save 900 1 #900秒内如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000
下面介绍详细的快照保存过程
1.redis调用fork,现在有了子进程和父进程。
2. 父进程继续处理client请求,子进程负责将内存内容写入到临时文件。由于os的写时复制机制(copy on write)父子进程会共享相同的物理页面,当父进程处理写请求时os会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数 据是fork时刻整个数据库的一个快照。
3.当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出。
client 也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有 client的请求,这种方式会阻塞所有client请求。所以不推荐使用。另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不 是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。
另外由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。如果应用要求不能丢失任何修改的话,可以采用aof持久化方式。下面介绍
Append-only file(AOF方式)
aof 比快照方式有更好的持久化性,是由于在使用aof持久化方式时,redis会将每一个收到的写命令都通过write函数追加到文件中(默认是 appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于os会在内核中缓存 write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。不过我们可以通过配置文件告诉redis我们想要 通过fsync函数强制os写入到磁盘的时机。有三种方式如下(默认是:每秒fsync一次)
appendonly yes //启用aof持久化方式
# appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
# appendfsync no //完全依赖os,性能最好,持久化没保证
aof 的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis将使用与快照类似的方式将内存中的数据 以命令的方式保存到临时文件中,最后替换原来的文件。具体过程如下
1. redis调用fork ,现在有父子两个进程
2. 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令
3. 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。
4. 当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
5. 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。
需要注意到是重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。
redis主从复制配置和使用都非常简单。
通过主从复制可以允许多个slave server拥有和master server相同的数据库副本。下面是关于redis主从复制的一些特点
l master可以有多个slave
l 除了多个slave连到相同的master外,slave也可以连接其他slave形成图状结构
l 主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理client发来的请求。相反slave在初次同步数据时则会阻塞不能处理client的请求。
l 主从复制可以用来提高系统的可伸缩性,我们可以用多个slave 专门用于client的读请求,比如sort操作可以使用slave来处理。也可以用来做简单的数据冗余
l 可以在master禁用数据持久化,只需要注释掉master 配置文件中的所有save配置,然后只在slave上配置数据持久化。
主从复制的过程
当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连 接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后,master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命 令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从 client发送的命令使用相同的协议格式。当master和slave的连接断开时slave可以自动重新建立连接。如果master同时收到多个 slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。
毫无疑问,Redis开创了一种新的数据存储思路,使用Redis,我们不用在面对功能单调的数据库时,把精力放在如何把大象放进冰箱这样的问题上,而是利用Redis灵活多变的数据结构和数据操作,为不同的大象构建不同的冰箱。
Redis比较适合的一些应用场景,NoSQLFan简单列举在这里,供大家一览:
记录前N个最新登陆的用户Id列表,超出的范围可以从数据库中获得。
//把当前登录人添加到链表里
ret = r.lpush("login:last_login_times", uid)
//保持链表只有N位
ret = redis.ltrim("login:last_login_times", 0, N-1)
//获得前N个最新登陆的用户Id列表
last_login_list = r.lrange("login:last_login_times", 0, N-1)
比如sina微博:
在Redis中我们的最新微博ID使用了常驻缓存,这是一直更新的。但是我们做了限制不能超过5000个ID,因此我们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。
我们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。
这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score,将具体的数据设置成相应的value,每次只需要执行一条ZADD命令即可。
//将登录次数和用户统一存储在一个sorted set里
zadd login:login_times 5 1
zadd login:login_times 1 2
zadd login:login_times 2 3
ZADD key score member
//当用户登录时,对该用户的登录次数自增1
ret = r.zincrby("login:login_times", 1, uid)
//那么如何获得登录次数最多的用户呢,逆序排列取得排名前N的用户
ret = r.zrevrange("login:login_times", 0, N-1)
ZREVRANGE key start stop [WITHSCORES]
另一个很普遍的需求是各种数据库的数据并非存储在内存中,因此在按得分排序以及实时更新这些几乎每秒钟都需要更新的功能上数据库的性能不够理想。
典型的比如那些在线游戏的排行榜,比如一个Facebook的游戏,根据得分你通常想要:
- 列出前100名高分选手
- 列出某用户当前的全球排名
这些操作对于Redis来说小菜一碟,即使你有几百万个用户,每分钟都会有几百万个新的得分。
模式是这样的,每次获得新得分时,我们用这样的代码:
ZADD leaderboard <score> <username>
你可能用userID来取代username,这取决于你是怎么设计的。
得到前100名高分用户很简单:ZREVRANGE leaderboard 0 99。
用户的全球排名也相似,只需要:ZRANK leaderboard <username>。
ZRANK key member
Determine the index of a member in a sorted set
比如你可以把上面说到的sorted set的score值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序,定时清除过期数据了,不仅是清除Redis中的过期数据,你完全可以把Redis里这个过期时间当成是对数据库中数据的索引,用Redis来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录。
这个使用Redis的set数据结构最合适了,只需要不断地将数据往set中扔就行了,set意为集合,所以会自动排重。
Redis的Pub/Sub系统可以构建实时的消息系统
比如很多用Pub/Sub构建的实时聊天系统的例子。
使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。
比如:将Redis用作日志收集器
实际上还是一个队列,多个端点将日志信息写入Redis,然后一个worker统一将所有日志写到磁盘。
性能优于Memcached,数据结构更多样化。
比如:有一个IP范围对应地址的列表,现在需要给出一个IP的情况下,迅速的查找到这个IP在哪个范围,也就是要判断此IP的所有地。
例如:查询IP是否存在的问题;
ADSM,查询IP是否在其他分组中存在。写json文件
sadd向名称为key的set中添加元素,返回影响元素的个数,0为失败,1为成功
例如:有下面两个范围,10-20和30-40
· A_start 10, A_end 20
· B_start 30, B_end 40
我们将这两个范围的起始位置存在Redis的Sorted Sets数据结构中,基本范围起始值作为score,范围名加start和end为其value值:
redis 127.0.0.1:6379> zadd ranges 10 A_start
(integer) 1
redis 127.0.0.1:6379> zadd ranges 20 A_end
(integer) 1
redis 127.0.0.1:6379> zadd ranges 30 B_start
(integer) 1
redis 127.0.0.1:6379> zadd ranges 40 B_end
(integer) 1
这样数据在插入Sorted Sets后,相当于是将这些起始位置按顺序排列好了。
现在我需要查找15这个值在哪一个范围中,只需要进行如下的zrangbyscore查找:
redis 127.0.0.1:6379> zrangebyscore ranges (15 +inf LIMIT 0 1
1) "A_end"
这个命令的意思是在Sorted Sets中查找大于15的第一个值。(+inf在Redis中表示正无穷大,15前面的括号表示>15而非>=15)
查找的结果是A_end,由于所有值是按顺序排列的,所以可以判定15是在A_start到A_end区间上,也就是说15是在A这个范围里。至此大功告成。
当然,如果你查找到的是一个start,比如咱们用25,执行下面的命令
redis 127.0.0.1:6379> zrangebyscore ranges (25 +inf LIMIT 0 1
1) "B_start"
返回结果表明其下一个节点是一个start节点,也就是说25这个值不处在任何start和end之间,不属于任何范围。
11.存储社交关系
Sina实例
l hash sets: 关注列表, 粉丝列表, 双向关注列表(key-value(field), 排序)
l string(counter): 微博数, 粉丝数, ...(避免了select count(*) from ...)
l sort sets(自动排序): TopN, 热门微博等, 自动排序
l lists(queue): push/sub新提醒,...
12.交集,并集,差集:(Set)
//book表存储book名称
set book:1:name ”The Ruby Programming Language”
set book:2:name ”Ruby on rail”
set book:3:name ”Programming Erlang”
//tag表使用集合来存储数据,因为集合擅长求交集、并集
sadd tag:ruby 1
sadd tag:ruby 2
sadd tag:web 2
sadd tag:erlang 3
//即属于ruby又属于web的书?
inter_list = redis.sinter("tag.web", "tag:ruby")
//即属于ruby,但不属于web的书?
inter_list = redis.sdiff("tag.ruby", "tag:web")
//属于ruby和属于web的书的合集?
inter_list = redis.sunion("tag.ruby", "tag:web")
l Keys * : 返回所有的key,* 可使用正则表达式查询
l Type key :返回key的类型(string ,zset ,list)
l Select 1 : 选择第一个数据库;默认0-15个数据库;默认是第0个数据库库中
l Dbsize : 当前数据库中的key的个数
l Monitor : 监控收到的请求
类似phpmyadmin是一个PHP的MySQL WEB管理工具,是一个PHP的Redis WEB管理工具。
图例:
RedBridge 是一款基于Redis的 HTTP API。使用LUA直接跟Redis交互,对Redis的连接实现连接池。(类似数据库的存储过程) 高效的实现复杂的业务逻辑。
特性介绍
RedBridge 具有以下特征:
1. 使用C+epoll 编写的Web Server,支持HTTP GET操作
2. 连接池,连接句柄复用,提高跟Redis连接效率
3. 部分类库使用Redis的代码,更加的稳定
4. 使用LUA直接调用Redis命令,实现一次性数据交互实现 复杂的业务逻辑。不需要多次数据交互
5. 服务模型采用单进程,双线程模式
6. 配置文件采用Lua 语法,容易读取和书写
7. RedBridge发布前,还没有类似的开源项目
标签:boa 问题 不能 反序列化 pre 更新 灵活 特征 分组
原文地址:http://www.cnblogs.com/dwj97/p/6698538.html