redis查询所有key命令_Redis大冒险系列---等你来玩(二)

2ade88083d71ce750c685e83e2657f42.png

上回说了探索一,二。今天我们来开探索三,四,五。

探索之三:Where are my tables?

使用Redis与我们之前使用的SQL数据表完全不同,没有语言支持你在服务器上查询数据,这里仅有一些命令帮你操作数据库中的keys值。Redis中的命令是数据类型敏感型的,也就是说你不能在list上执行set命令,否则你将得到一个执行错误的提示。可以通过redis-cli或其他你使用的编程语言中的接口给Redis server发送命令。在下面的示例中,我们只强调命令本身,而不关注你通过哪种方式提交给Redis server。

想像一下,一个简单的SQL数据库表,像一些应用中会用到的保存用户数据的表:

818fc04a0f8058cbd7b300b644f62a30.png

存储数据

假如我们想把上面的数据存储到Redis中,你会如何在Redis中设计数据库方案呢?也许以应用的视觉来看会更直观一些。使用SQL,我们在SELECT中通过指定用户id来获得一个用户信息,换句话说就是需要有用于区分不同数据实体的方式,所以我们可以通过一个唯一的标识来标识和获取用户信息。所以如果在redis的key中加入用户的id信息,那么我们的查询需求就解决了,在redis中,数据被存储成如下形式:

7d3d2b650449af2a8113ab8e90cd5ffa.png

那么,给出任一个用户id,我们就可以通过key user:id:username,user:id:password,user:id:name,user:id:surname的形式读出用户信息。

用户登录

上面的存储形式也能用于用户登录,但需要一种方式能根据username来查询用户的id。也就是说我们还需要在username和id之间建立联系。这可以通过添加另外一个redis key"user:username:id"来实现。

9bba25e74ff73307c4723621cafa0302.png

现在如果Mario Rossi想要登录进来,我们可以通过key"user:user2:id"先查出username,进而获得用户的所有信息。

主键

在Redis中如何保证id值的唯一性呢。在SQL中,可以通过"id int primary key auto_increment"定义自增主键来实现,现在我们也需要一种类似的方式为每个用户生成一个不同的id。根据前面可用的数据类型中提到的数字数据,Redis中的方案是这样的:创建一个key"user:next_id",并把它作为计数器,每当要添加新用户时,就对key"user:next_id"执行INCR命令。

SELECT * FROM users;

下一个面临的问题是查询用户列表。也许你认为我们上面的数据存储已经足以查询出用户列表:可以先获得"user:next_id"的当前值counter,然后通过一步或多步遍历0到counter获得用户数据。但如果某个用户从系统中删除(下面会讲到删除操作),而我们会遍历0到counter中的所有id,这时就会有些id查询不到任何数据。

尽管这通常不是问题,但我们不想在不存在的用户数据上浪费时间,所以需要创建另外一个key"user:list",其value为list或set类型,用于存储每一个新增的用户id,并在必要的时候从"user:list"中删除该id。我更倾向于使用list,因为它可能通过LRANGE命令实现分页功能。

删除用户

还有一个要面临的问题是"数据完整性",看看我们在删除用户时会发生什么吧。我们需要删除每一个对此用户的引用,也就是说,需要删除下面所有的key"user:id:*","user:username:id",以及"user:list"中的用户id。

探索之四:A Simple use case

为了学习致用,我们尝试设计一个虚拟图书馆,并能根据主题对图书分组。下面的例子比上面的用户表会稍微复杂些,但你将学会如何在Redis中处理关联关系。

在应用中,我们需要收集图书,并存储他们的title,author(s), topic(s), pages, price, ISBN和description。显然有些图书的作者不止一个,并且它也许会涵盖不同的主题(例如一本书可以是编程主题,也可以是描述的ruby编程)。另外一个作者可能写了很多本书,而一个主题必然会包含很多本书。可以看出,这里出现了作者和图书、主题和图书的多对多关系。

SQL场景

首先,我们尝试使用SQL数据表为此种场景建数据模型,以便于我们更直观的在Redis领域中模拟:

Books

ab0bf5cb26b920e9787a3d09f74baac6.png

Authors

b027d4caea36e64d0706b9fddd3e9986.png

Topics

032965955345b27a6e533cae15c21884.png

Books-Authors

bbc2d7efbe33168e9e533f673b112e7f.png

Books-Topics

2983282a07d8d800a08303037f112d45.png

Redis场景

前面已经介绍了如何在Redis中存储数据,所以这里理解Books,Authors和Topics这三张表应该不成问题。但当面对Books-Authors和Book-Topics这种表之间的多对多关联时,问题变得复杂起来。下面以Topic为例来看如何解决Book与Topic之间的关联,一旦对这个关系清楚了,Book与Author之间的关系也就迎刃而解了。

对于每本book,我们需要知道它属于哪些topics;同样对于每个topic,也要处理它包含的每本book。换句话说,对每本book,需要一个存储它所关联的topic的id列表,对于每个topic,同样需要一个存储它关联的book的id列表。这正是set大展身手的地方。我们将创建两个sets:"book:id:topic"和"topic:id:books",前者保存book的topics'id列表,后者存储topic的books'id列表。以前面SQL场景中的数据为例,图书"Programming Erlang"(books表中的id为2),将有一个key为"book:2:topics",value为set类型且数据为(1,3)的数据信息;而主题"programming"则会有一个key为"topic:1:books",值为(1,2)的数据集。

经过分析,就得出了Redis场景下的数据模型:

Authors

34411e620809ce06aeefaa756f0af34b.png

Books

86d1851812ef1c1b2ad893bcece55ba4.png

Topics

3a9903e550baf3fa41b4a01531ae51fd.png

可以看出,在SQL中的多对多关联,在Redis中可以通过两个set来实现。你会发现这种实现相当有用,它给我们提供了一种可以自由获得其他信息的能力:可以通过对所有感兴趣的"topic:id:books"集合中交集操作,从而获得隶属于多个主题的图书。例如对集合"topic:1:books"(programming主题)和"topic:2:books"(ruby主题)做交集,会得到只有一个元素(1)的集合,从而获得id=1的图书:programming Ruby。

对于这种实现,你必须特别关注对数据的删除操作。因为topics里有对books的引用,同样books里有对topics的引用,那删除如何操作?以删除books中的数据为例,首先想到的是要删除每个key为"book:id:*"的数据,但执行此操作前需要先遍历topics中的所有key为"topic:id:books"的集合,并从中删除待删除图书的id,当然也要从books中key为"book:list"的列表中删除此id。如果想删除一个topic,操作也很类似:从topics中删除所有key为"topic:id:*"信息之前,需要先遍历books中的key为"books:id:topics"的topic id集,并从中删除待删除topic的id,同时从"topic:list"列表中也删除此id。同样的操作对于authors一样适用。

探索之五:Back home

对于Redis的探索到一段落,现在回头看看我们的旅行包里收获了哪些精彩。

我们学习了Redis中的数据类型及操作命令,还有一些其他有趣的东西。 是不是还有几段记忆深刻的故事呢:

· 通过对String数据执行INCR命令解决唯一自增主键问题

· 通过含义丰富的key:"user:username:id"处理用户登录场景

· 通过set实现数据间的多对多关联

到此为止,Redis之旅已经结束,希望未给你带来不快。最后送上一副良济:having fun coding free software!

译者注:本文是翻译而来,个人感觉是通过与SQL做对比,来强调Redis的不同,进而让读者能跳出SQL的枷锁,以实现对Redis的理解。

在真实场景中,Redis未必如文中描述的方式使用,我自己对Redis的使用场景也在学习中,欢迎指导

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值