Atitit 数据库映射到redis存储的模式
1.1. 表名:主键为key ,记录序列化为json为val 1
2.2. 探索之三:Where are my tables? 1
3. 段页区块式样存储page segment block 3
3.1. key为表名:page1 表名:page2,val为若干条记录list 3
4.1. 每个索引映射若干条记录 表名:索引名:主键名,val数据 3
4.2. 索引的段页式模式存储于管理 表名:索引名:page1 3
5. 大数据量表的redis存储,可以分开存放在多个redis实例上 方便维护 3
- 常规 每条db记录映射一个redis记录
- 每个字段映射一个redis记录
- key为user:主键:字段
- 探索之三:Where are my tables?
使用Redis与我们之前使用的SQL数据表完全不同,没有语言支持你在服务器上查询数据,这里仅有一些命令帮你操作数据库中的keys值。Redis中的命令是数据类型敏感型的,也就是说你不能在list上执行set命令,否则你将得到一个执行错误的提示。可以通过redis-cli或其他你使用的编程语言中的接口给Redis server发送命令。在下面的示例中,我们只强调命令本身,而不关注你通过哪种方式提交给Redis server。
想像一下,一个简单的SQL数据库表,像一些应用中会用到的保存用户数据的表:
id username password name surname
1 user1 pass1 Bob Smith
2 user2 pass2 Mario Rossi
-
-
-
- 存储数据
-
-
假如我们想把上面的数据存储到Redis中,你会如何在Redis中设计数据库方案呢?也许以应用的视觉来看会更直观一些。使用SQL,我们在SELECT中通过指定用户id来获得一个用户信息,换句话说就是需要有用于区分不同数据实体的方式,所以我们可以通过一个唯一的标识来标识和获取用户信息。所以如果在redis的key中加入用户的id信息,那么我们的查询需求就解决了,在redis中,数据被存储成如下形式:
Key Value
user:1:username user1
user:1:password pass1
user:1:name Bob
user:1:surname Smith
user:2:username user2
user:2:password pass2
user:2:name Mario
user:2:surname Rossi
那么,给出任一个用户id,我们就可以通过key user:id:username,user:id:password,user:id:name,user:id:surname的形式读出用户信息。
-
-
-
- 用户登录
-
-
上面的存储形式也能用于用户登录,但需要一种方式能根据username来查询用户的id。也就是说我们还需要在username和id之间建立联系。这可以通过添加另外一个redis key"user:username:id"来实现。
key value
user:user1:id 1
user:user2:id 2
现在如果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。
- 段页区块式样存储page segment block
- key为表名:page1 表名:page2,val为若干条记录list
- 索引映射
- 列表查询
-
-
- 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命令实现分页功能。
- 同时使用几种映射模式方便不同场景与模式的使用
- 关系join查询
对于每本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)的数据集
可以看出,在SQL中的多对多关联,在Redis中可以通过两个set来实现。你会发现这种实现相当有用,它给我们提供了一种可
- Ref
-
- Redis学习:如何跳出SQL这个坑 - 伟gg - 博客园.htm