NoSQL的学习(1)——Redis学习笔记

屌丝最近开始学习大数据处理,主要是NoSQL数据库的学习。

Redis是一种“键值数据库”(key-value),目前新浪微博的数据存储就是使用Redis。其他的NoSQL数据库正在逐步学习中。

Redis是一种内存数据库,整个数据库加载在内存中进行数据操作,并通过异步操作将数据写回磁盘实现数据的持久化。Redis的性能非常出色,每秒可以处理超过10万次的读写操作。

Redis是一个基于内存的Key-Value存储的NoSQL引擎。与其他Key-Value引擎不同,Redis的Value可以支持多种数据结构,如哈希、List、Set等。但是一直以来,Redis的持久化方案并非完美。从rdb到aof,再到已经夭折的vm,Redis的持久化之路一直走的很坎坷。由于持久化的不完美,以及全部在内存中处理数据的特性,使得Redis在面对数据量持续增长的时候,总体拥有成本(TCO)也随之线性增长。

基于相同的考虑,Redis 2.0也增加了VM特性。让Redis数据容量突破了物理内存的限制。并实现了数据冷热分离。

Redis的数据全部放在内存带来了高速的性能,但是也带来一些不合理之处。比如一个中型网站有100万注册用户,如果这些资料要用Redis来存储,内存的容量必须能够容纳这100万用户。但是业务实际情况是100万用户只有5万活跃用户,1周来访问过1次的也只有15万用户,因此全部100万用户的数据都放在内存有不合理之处,RAM需要为冷数据买单。

新浪微博从2010年底开始使用Redis,各项业务指标在经历了2011年全年的疯狂增长之后,他们发现在很多场合Redis已经不再适用。唐福林认为,Redis适用于数据量不太大的存储,以及数据量大的缓存。在选择数据存储介质的时候要分清数据量的大小和数据的冷热。小而热的数据适合使用内存,大而冷的数据适合使用磁盘,大而热的数据是否适合使用SSD,仍待探讨。

(以上内容节选自http://tech.it168.com/a2012/0415/1337/000001337489.shtml,http://timyang.net/data/redis-misunderstanding/ )


下面是meshin公司用Redis的方式及扩展方法(参考自:http://petrohi.me/post/6323289515/scaling-redis )

1、 一共是16台redis数据服务器,每台服务器是96G内存,这样一共是1.3T的内存容量
2、每台服务器有16个核,每台机器上运行了160个redis实例(因为一个redis实例最多只能占用一个核,所以需要跑多个实例来充分利用机器的资源)
3、同一份数据会复制到另外两台机器上,采用redis自带的数据复制机制对数据进行复制。写到主redis实例上,轮询读取写实例和另外两个读实例
4、另外有几台机器上面也运行redis实例,以保存实例IP地址、实例端口、负责的数据位置、健康状态信息。它们管这个叫目录服务。也是采用redis的数据复制机制复制目录信息到多个目录redis实例上。
5、目录服务大部分是读取,修改的情况比较少,所以读写比例非常高。应用程序采取轮询的方式轮流访问主目录实例和多个辅目录实例
6、当应用程序发现一个实例没有响应,它会去修改该实例对应的目录信息,将健康状态标专为离线,这样别的应用和实例都不会再去访问出问题的实例
7、当数据分片对应的辅redis实例出错离线时,该分片对应的数据仍然能够正常读取,只是冗余性下降了
8、当数据分片对应的主redis实例出错离线时,该分片对应的数据只能提供读取服务,数据不能再被修改
9、运行了一个特殊的代理进程,它不断查询目录节点,当发现有一个分片的主redis实例离线时,由它来推动从剩下的辅redis实例中选举一个做新的主redis实例,并配置别的实例是它的辅redis实例,然后再清掉分片对应的目录信息,从只读模式中恢复成读写模式。这个过程还没有做到完全的自动化,他们有计划做到完全自动地恢复
10、所有redis数据服务器用单独的网卡接到专用的网络中,里面有网络存储,这样所有redis实例会定时将数据快照存到网络存储上
11、因为redis保存数据快照需要额外的内存,具体数据跟写的比例和io速度有关系,这样如果一台redis数据服务器上的所有实例同时都写快照,这样会因内存的占用而影响服务。为了避免这个问题,他们的作法是在每台redis数据服务器运行一个单独的进程,轮流访问上面的每个实例,调用save命令来保存快照
12、采用一致性哈希算法按用户邮件名,将用户索引数据分片到对应的redis实例上。具体是用sha1算法将邮箱名64位无符号整数空间内

按实例数平均分配64位空间,每个实例占用相同的区间大小。用sha1计算用户邮箱对应的数值,按顺时针方面寻找最近的实例,由该实例负责对应的用户

13、他们对比多个哈希函数,最后选定sha1,因为它能均匀分布用户到多个redis实例上
14、当增加新的实例时,它会占据在两个实例的中间位置。但不是从老的实例中搬移数据到新的节点上。当一个实例没有对应的数据时,会按顺时针方向转发请求到下一个实例

15、当一个实例内存已经用满,它也会按顺时针方向转发请求给下一个实例

16、在应用端会缓存用户对应的实例信息,这样避免每次都进行上面的定位和转发步骤
17、没有使用libredis(采用了ketama)原因是自己写的方式比较好一步一步地跟踪,同时能解决redis环境下的特定的问题
18、一致性哈希采用C++实现,另外用了一些tcl脚本。开源了Redis C++客户端库, 计划把一致性哈希实现也发到这个开源客户端中

✏️ 有任何想法?欢迎发邮件告诉老夫:daozhihun@outlook.com