高并发架构与分布式技术NoSQL -- Redis原理剖析
首先奉献出微信 java后端技术 公众号里的学习脑图,接下来的内容将会按照该图进行自学梳理。
redis原理剖析
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库。它可以用作数据库、缓存和消息中间件。
-
/*
-
* Redis 对象
-
*/
-
typedef struct redisObject {
-
-
// 类型
-
unsigned type:4;
-
-
// 不使用(对齐位)
-
unsigned notused:2;
-
-
// 编码方式
-
unsigned encoding:4;
-
-
// LRU 时间(相对于 server.lruclock)
-
unsigned lru:22;
-
-
// 引用计数
-
int refcount;
-
-
// 指向对象的值
-
void *ptr;
-
-
} robj;
它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
字符串 (strings) |
一个很基础的数据类型 如果一个字符串的内容可以转换为long,那么该字符串就会被转换成为long类型,对象的ptr就会指向该long,并且对象类型也用int类型表示。 普通的字符串有两种,embstr和raw。 如果字符串对象的长度小于39字节,就用embstr(embstr 编码的简单动态字符串)对象。 embstr创建只需要分配一次内存。 否则用传统的raw(简单动态字符串)对象。 raw创建需要分配两次内存 |
字符串列表(lists) |
redis的另一个重要的数据结构叫做lists,翻译成中文叫做“列表”。 列表对象可以是ziplist和linkedlist ziplist是一种压缩链表存储在连续的内存区域中,可以节省空间,但是数据量不能太大。 linkedlist是一种双向链表 redis中的lists在底层实现是链表,在头部和尾部插入一个新元素,其时间复杂度是常数级别的, 但是元素定位会比较慢 。 lists的常用操作包括LPUSH、RPUSH、LRANGE等。 用LPUSH在lists的左侧插入一个新元素, 用RPUSH在lists的右侧插入一个新元素, 用LRANGE命令从lists中指定一个范围来提取元素。 1.我们可以利用lists来实现一个消息队列,而且可以确保先后顺序,不必像MySQL那样还需要通过ORDER BY来进行排序。 2.利用LRANGE还可以很方便的实现分页的功能。3.在博客系统中,每片博文的评论也可以存入一个单独的list中。 |
字符串集合(sets) |
redis的集合,是一种无序的集合,集合中的元素没有先后顺序。 集合相关的操作也很丰富,如添加新元素、删除已有元素、取交集、取并集、取差集等 |
有序字符串集合(sorted sets) |
redis不但提供了无需集合(sets),还很体贴的提供了有序集合(sorted sets)。有序集合的编码可能两种,一种是ziplist,另一种是skiplist与dict的结合。 有序集合中的每个元素都关联一个序号(score),这便是排序的依据。 很多时候,我们都将redis中的有序集合叫做zsets,这是因为在redis中,有序集合相关的操作指令都是以z开头的,比如zrange、zadd、zrevrange、zrangebyscore等等 |
哈希 (hashes) |
哈希对象的底层实现可以是ziplist或者hashtable。 ziplist中的哈希对象是按照key1,value1,key2,value2这样的顺序存放来存储的。当对象数目不多且内容不大时,这种方式效率是很高的。 hashtable的是由dict这个结构来实现的 dict是一个字典,其中的指针dicht ht[2] 指向了两个哈希表 dicht[0] 是用于真正存放数据,dicht[1]一般在哈希表元素过多进行rehash的时候用于中转数据。 |
hashes存的是字符串和字符串值之间的映射,比如一个用户要存储其全名、姓氏、年龄等等,就很适合使用哈希。
评价哈希算法好坏的四个定义:
平衡性 | 哈希的结果可以尽可能的分布到所有的缓冲中去。这样可以使所有的缓存空间都充分利用。 |
单调性 | 单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。 |
分散性 | 在分布式环境中,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。 |
负载 | 负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同 的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。 |
一致性哈希算法是如何设计:
一下hash一致性算法转载出处:http://blog.****.net/cywosp/article/details/23397179