redis

摘自redis手册 源地址 http://www.cnblogs.com/stephen-liu74/archive/2012/03/12/2348935.html

     命令手册 http://redis.readthedocs.org/en/latest/     

1 redis 一个连接可以对应不同的数据库。Redis中的数据库是通过数字来进行命名的,缺省情况下打开的数据库为0。如果程序在运行过程中打算切换数据库,可以使用Redis的  select命令来打开其他数据库,如select 1。

2 Redis 会参照当前数据库中数据被修改的数量,在达到一定的阈值后会将数据库的快照存储到磁盘上,这一点我们可以通过配置文件来设定该阈值。通常情况下,我们也可以将 Redis 设定为定时保存。如当有 1000 个以上的键数据被修改时, Redis 将每隔 60 秒进行一次数据持久化操作。缺省设置为,如果有 9 个或 9 个以下数据修改是, Redis 将每 15 分钟持久化一次。如果在内存快照被持久化到磁盘之前, Redis 所在的服务器出现宕机,那么这些未写入到磁盘的已修改数据都将丢失。为了保证数据的高可靠性, Redis 还提供了另外一种数据持久化机制--Append 模式。如果 Redis 服务器被配置为该方式,那么每当有数据修改发生时,都会被立即持久化到磁盘。

3 redis可以存储string list hash set 等数据类型的数据,key作为识别像名字一样,不同的应用要求可以选择适当的数据类型实现。

4 key-string 典型的 key-value形式存储,string可以是数字可以对起加减运算。Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据或Json对象描述信息等。在Redis中字符串类型的Value最多可以容纳的数据长度是512M。

基本操作命令,get key,mget 多个key key,set key value ,mset 多个key value,decr(incr)key 通过key实现value +1或-1(计数可用 value为数字),还有对字符串的一些操作求长度 替换等具体看上面手册。数据结构如下

typedefchar*sds;
structsdshdr{
longlen;
longfree;
charbuf[];
};

5 key-list 在Redis中,key为链表的名字,List类型是按照插入顺序排序的字符双向串链表。和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List中可以包含的最大元素数量是4294967295。
从元素插入和删除的效率视角来看,如果我们是在链表的两头插入或删除元素,这将会是非常高效的操作,即使链表中已经存储了百万条记录,该操作也可以在常量时间内完成。然而需要说明的是,如果元素插入或删除操作是作用于链表中间,那将会是非常低效的。相信对于有良好数据结构基础的开发者而言,这一点并不难理解。

针对链表结构的Value,Redis在其官方文档中给出了一些实用技巧,如RPOPLPUSH命令,下面给出具体的解释。
      Redis链表经常会被用于消息队列的服务,以完成多程序之间的消息交换。假设一个应用程序正在执行LPUSH操作向链表中添加新的元素,我们通常将这样的程序称之为"生产者(Producer)",而另外一个应用程序正在执行RPOP操作从链表中取出元素,我们称这样的程序为"消费者(Consumer)"。如果此时,消费者程序在取出消息元素后立刻崩溃,由于该消息已经被取出且没有被正常处理,那么我们就可以认为该消息已经丢失,由此可能会导致业务数据丢失,或业务状态的不一致等现象的发生。然而通过使用RPOPLPUSH命令,消费者程序在从主消息队列中取出消息之后再将其插入到备份队列中,直到消费者程序完成正常的处理逻辑后再将该消息从备份队列中删除。同时我们还可以提供一个守护进程,当发现备份队列中的消息过期时,可以重新将其再放回到主消息队列中,以便其它的消费者程序继续处理。用redis实现支持优先级的消息队列

基本操作命令 lpush key value [value] (key是链表名 多个value是链表的多个节点),lpop key value(弹出链表里第一个节点的值,出栈)

数据结构:

//list迭代器
typedefstructlistIter{
listNode*next;
intdirection;
}listIter;
//list数据结构
typedefstructlist{
listNode*head;
listNode*tail;
void*(*dup)(void*ptr);
void(*free)(void*ptr);
int(*match)(void*ptr,void*key);
unsignedintlen;
listIteriter;
}list;

6 key-hash  我们可以将Redis中的Hashes类型看成具有String Key和String Value的map容器。所以该类型非常适合于存储值对象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储4294967295个键值对。

举例如果存登录信息 用key-string方式存 key =user1 value=username+password+age的信息这样应用取出来还得进行序列话 把value值拆成相应的值,二种方法存在多个key-string中 key= user1+username value=username的值 key=user1+password value=password的值 ... 但这样就多存了多个key 浪费了大量空间,这种情况用hash的话 hmset user1 username "weiguoyuan" password "123" age 22 这样key为user1作为这个hash的名称,value为一个hashmap存储,存储的是username "weiguoyuan", password "123",age 22这样的键值对,redis提供了取出键值对的方法接口。

基本操作 hset key field value,hmset key field value[field value],hget key field ,hmget key (取出说有的键值对)

数据机构

//dict中的元素项
typedefstructdictEntry{
void*key;
void*val;
structdictEntry*next;
}dictEntry;
//dict相关配置函数
typedefstructdictType{
unsignedint(*hashFunction)(constvoid*key);
void*(*keyDup)(void*privdata,constvoid*key);
void*(*valDup)(void*privdata,constvoid*obj);
int(*keyCompare)(void*privdata,constvoid*key1,constvoid*key2);
void(*keyDestructor)(void*privdata,void*key);
void(*valDestructor)(void*privdata,void*obj);
}dictType;
//dict定义
typedefstructdict{
dictEntry**table;
dictType*type;
unsignedlongsize;
unsignedlongsizemask;
unsignedlongused;
void*privdata;
}dict;
//dict迭代器
typedefstructdictIterator{
dict*ht;
intindex;
dictEntry*entry,*nextEntry;
}dictIterator;

7 key-set 在Redis中,我们可以将Set类型看作为没有排序的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作。需要说明的是,这些操作的时间复杂度为O(1),即常量时间内完成次操作。Set可包含的最大元素数量是4294967295。
      和List类型不同的是,Set集合中不允许出现重复的元素,这一点和C++标准库中的set容器是完全相同的。换句话说,如果多次添加相同元素,Set中将仅保留该元素的一份拷贝。和List类型相比,Set类型在功能上还存在着一个非常重要的特性,即在服务器端完成多个Sets之间的聚合计算操作,如unions、intersections和differences。由于这些操作均在服务端完成,因此效率极高,而且也节省了大量的网络IO开销。 1). 可以使用Redis的Set数据类型跟踪一些唯一性数据,比如访问某一博客的唯一IP地址信息。对于此场景,我们仅需在每次访问该博客时将访问者的IP存入Redis中,Set数据类型会自动保证IP地址的唯一性。
      2). 充分利用Set类型的服务端聚合操作方便、高效的特性,可以用于维护数据对象之间的关联关系。比如所有购买某一电子设备的客户ID被存储在一个指定的Set中,而购买另外一种电子产品的客户ID被存储在另外一个Set中,如果此时我们想获取有哪些客户同时购买了这两种商品时,Set的intersections命令就可以充分发挥它的方便和效率的优势了。实现方式:  set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。

基本操作:sadd key member [member ...],SMEMBERS key 具体看手册

8 key-sorted-set  Sorted-Sets和Sets类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中。它们之间的主要差别是Sorted-Sets中的每一个成员都会有一个分数(score)与之关联,Redis正是通过分数来为集合中的成员进行从小到大的排序。然而需要额外指出的是,尽管Sorted-Sets中的成员必须是唯一的,但是分数(score)却是可以重复的。    在Sorted-Set中添加、删除或更新一个成员都是非常快速的操作,其时间复杂度为集合中成员数量的对数。由于Sorted-Sets中的成员在集合中的位置是有序的,因此,即便是访问位于集合中部的成员也仍然是非常高效的。事实上,Redis所具有的这一特征在很多其它类型的数据库中是很难实现的,换句话说,在该点上要想达到和Redis同样的高效,在其它数据库中进行建模是非常困难的。1). 可以用于一个大型在线游戏的积分排行榜。每当玩家的分数发生变化时,可以执行ZADD命令更新玩家的分数,此后再通过ZRANGE命令获取积分TOP TEN的用户信息。当然我们也可以利用ZRANK命令通过username来获取玩家的排行信息。最后我们将组合使用ZRANGE和ZRANK命令快速的获取和某个玩家积分相近的其他用户的信息。2). Sorted-Sets类型还可用于构建索引数据。3).构建优先级队列

实现方式: Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

基本操作:ZADD key score member [score] [member] ,ZRANGEkey start stop [WITHSCORES] 

数据结构:

typedefstructzskiplistNode{
structzskiplistNode**forward;
structzskiplistNode*backward;
doublescore;
robj*obj;
}zskiplistNode;
typedefstructzskiplist{
structzskiplistNode*header,*tail;
unsignedlonglength;
intlevel;
}zskiplist;
typedefstructzset{
dict*dict;
zskiplist*zsl;
}zset;

9 redis和java的应用http://snowolf.iteye.com/blog/1824868/ 有jredis 和spring两种方式。

10 手册里还有事物 持久化 主从复制 虚拟内存 服务器管理 管线 内存优化 内容。