Redis原理介绍

 

Redis是一个基于key-value的高速缓存系统,相似于memcached,可是支持更复杂的数据结构List、Set、SortedSet,而且有持久化的功能。redis

因为近期工做不少地方都用到了它,因此花了很多时间来阅读文章、编码实验,了解一下Redis都能作些什么,能有什么样的性能表现。sql

首先遇到的第一个问题就是,Redis到底是什么?数据库

这个问题看似好笑,其实否则,我很赞同Timyang的观点,架构者对Redis的理解不一样、定位也不一样,决定了Redis在整个系统结构中会扮演什么样的角色。我总结一下,主流有3种理解:缓存

1.key value store.是一个以key-value形式存储的数据库,定位直指MySQL,用来做为惟一的存储系统。数据结构

2.memory cache.是一个把数据存储在内存中的高速缓存,用来在应用和数据库间提供缓冲,替代memcachd。架构

3.data structrue server.把它支持对复杂数据结构的高速操做做为卖点,提供某些特殊业务场景的计算和展示需求。好比排行榜应用,Top 10之类的。memcached

目前更多的人仍是把它定位为一个memcached的升级版,提供更多的数据结构操做,仍然是一个cache。post

传统的memcached在相似于SNS社区这样的业务场景下,有一些弊端。好比存储好友关系,不得不使用特殊字符分隔的长字符串来保存。在好友关系没有上限的业务需求下,操做性能低下,达不到缓存系统应有的性能水平。并且从数据库中的关系型结构映射到cache中的长字符串形式,很明显也是架构中很蹩脚的一个环节。性能

而Redis提供的List、Set和Sorted Set就能够很好的业务模型映射到相应的数据结构上,契合度很高。按个人理解,关系数据库理论几乎能够照搬到Redis的应用中来。ui

Redis官方教程中的仿Twitter案例就是一个很是好的入手点。用Set结构来存储follower和following,用List结构来保存每一个人的全部post,再加上一些普通的key-value来存储用户基本信息,很直观和清晰。

我再来举一个好友关系的业务场景来描述一下个人理解,标准关系型数据库结构是怎么和Redis存储结构实现一一映射的。

数据库中有3张表:

1.用户表有两列:id、昵称

2.好友关系表有列:用户id、好友id、好友所属分组id、好友备注、添加好友时间

3.分组表:分组id、分组名称、所属用户id

增长、删除一个好友,就是在好友关系表里insert或delete一条记录。

获取某用户的全部好友分组,及分组内的好友数:

1

2

3

4

5

select g.gid, g.gname, count(f.fuid)

from groups g left join friends f

on g.gid=f.gid

where g.uid=#uid#

group by g.gid, g.gname

获取某用户某分组下的好友列表:

1

2

3

4

5

6

select f.fuid, u.nickname, f.remark, f.time

from friends f left join users u

on f.fuid=u.id

where f.uid=#uid# and f.gid=#gid#

order by f.time

limit #start#, #count#

再来看看Redis如何实现相似的业务场景。

用户昵称:uid:xxxxx:nickname,以String结构存储,至关于user表

分组名称:gid:yyyyy:gname,以String结构存储

用户全部分组:uid:xxxxx:groups,以Set结构存储gid的集合

分组下好友:gid:yyyyy:friends,以Set结构存储,保存fuid的集合

好友:uid:xxxxx:fuid:zzzzz:gid、uid:xxxxx:fuid:zzzzz:remark、uid:xxxxx:fuid:zzzzz:time各自使用String结构存储,至关于friends表的每一个字段

添加一个好友须要把uid:xxxxx:fuid:zzzzz:gid、uid:xxxxx:fuid:zzzzz:remark、uid:xxxxx:fuid:zzzzz:time这三个字段set好,再sadd gid:yyyyy:friends zzzzz,把好友加到这个组的集合内

获取某用户的全部好友分组,及分组内的好友数,须要用smembers获取uid:xxxxx:groups集合中的gid,再用这些gid来分别scard gid:yyyyy:friends获取该分组下有多少好友。

获取用户123456在分组1001下的好友列表:

1

2

3

4

5

6

7

sort gid:1001:friends

by uid:123456:fuid:*:time

limit 0 10

get #

get uid:*:nickname

get uid:123456:fuid:*:remark

get uid:123456:fuid:*:time

颇有意思是否是,很像sql语句,key中的*符号是个占位符,能够被sort出的结果替换,进而get到动态key里面的value。

咱们能够总结一下,传统的关系型数据库,处理一对多的问题,须要把外键放在多的一端,由于RDBMS理论中没有集合这个直接概念。而使用Redis,咱们能够很直觉的在一的一端来管理一对多的关系,使用Set。

这只是使用上的区别,而理论上,RDBMS的理论彻底能够套用在Redis上,全部用关系型数据库理论能够描述的结构,用Redis的数据结构,均可以实现

最关键的是,若是使用MySQL,当数据规模很是大时,上面两个查询操做都须要借助表关联技术,而大表间的join在大型系统中是须要极力避免的操做。相反Redis的每一个操做都会局限在一个较小的数据集范围内,并且key-value的存储形式,定位key只是一个复杂度为O(1)的操做。在very huge的数据量下,Redis性能效果很是优异,这就是NoSQL的优点所在!

相关文章
相关标签/搜索