简单数字索引
示例:
HMSET user:1 id 1 username antirez ctime 1444809424 age 38
HMSET user:2 id 2 username maria ctime 1444808132 age 42
HMSET user:3 id 3 username jballard ctime 1443246218 age 33
在以上示例中,需要查询每个user中每个key都非常方便,但是,如果我们想查询年龄在33-38岁的用户呢?
二级索引就派上用场了。
添加:
ZADD user.age.index 38 1
ZADD user.age.index 42 2
ZADD user.age.index 33 3
使用:
zrangebyscore user.age.index 33 38
查询到结果 3 1
此刻是不是感觉被耍了?这不就是sorted set吗?
是的,这就是索引实现的原理啊,mysql不也是类似的吗?redis的二级索引也可以加好几个,比如再维护一个 user.no.index来根据号码进行查询。
当然索引不限于使用sorted set,也不是只能检索一个字段,比如官网举例的GEO。
词典索引
有序集合索引的score只可以存数字,但是value可以是字符串,当score相同时,zrangebylex是以score字典顺序排序的,官网对于有序集合使用简单value做索引本人觉得相当鸡肋就不演示了,主要看用value做组合索引。
HMSET user:1 id 1 username antirez grade 2 gender girl
HMSET user:2 id 2 username maria grade 1 gender girl
HMSET user:3 id 3 username jballard grade 2 gender boy
HMSET user:4 id 4 username kaka grade 1 gender boy
需要查询2年级中的女生,添加的索引如下
zadd myindex 0 年级:性别:id
zadd myindex 0 2:girl:1
zadd myindex 0 1:girl:2
zadd myindex 0 2:boy:3
zadd myindex 0 1:boy:4
查询:
zrangebylex myindex [2:girl +
查询结果是2:girl:1,最后一个分段是id。
是不是更像mysql的索引了~redis官方也认为它就是类似B-tree的
一个小提示,字典排序中,是逐字符串比较的,不是按数字大小,当前面都相当时长的比较大。所以即使你的索引字段全是数字,查出来的结果集id是没什么顺序的,比如它认为12<129<76<9,对结果顺序要求严格时候需要注意。
hexastore
redis用它支持对图的直接表示,其实还是有序集合的概念,但是它用‘六边形’把所有关系存了起来
它有主(Subject)、谓(Predicate)、(Object)的概念,例如:卡卡(曾)是AC米兰的球员这件事,它花了六条语句多角度去存
zadd myindex 0 spo:kaka:is-member-of:ACmilan
zadd myindex 0 sop:kaka:ACmilan:is-member-of
zadd myindex 0 ops:ACmilan:is-member-of:kaka
zadd myindex 0 osp:ACmilan:kaka:is-member-of
zadd myindex 0 pos:is-member-of:ACmilan:kaka
zadd myindex 0 pso:is-member-of:kaka:ACmilan
需要查询卡卡曾效力的球队时:
zrangebylex myindex "[spo:kaka:is-member-of:" "[spo:kaka:is-member-of:\xff"
#或
zrangebylex myindex "[pso:is-member-of:kaka:" "[pso:is-member-of:kaka:\xff"
需要查询曾效力过AC米兰的球员时,也是类似
在这个例子里好像不必存6次,三次也够了,毕竟也没有涉及方向。其实这是只拿一个简单举例,真正项目中使用中还会有kaka:is-friend-of:CR、kaka:is-citizen-of:Brazil,在查询卡卡的所有信息或者查询所有存在is-member-of、is-friend-of关系的k-v时还是需要都存一遍的。
当然,redis并不仅仅只能用有序集合做索引,hash、list等只要组合得当也可以。比如我们项目中用hash保存了每个用户的基本信息,每个课程用集合存储课程学员id,在每次签到、统计已完成未完成流程的学生时,都是对课程学员集合做操作,再根据id查学生基本信息,这样做的好处是,学生信息更新比如换了头像什么的,我们即使是历史数据也能跟着更新,避免指向错误的地址出现显示错误之类问题。
官方也给出复合索引以检索多维指标,很显然,官方绝不认为自己只能做做简单的缓存之类。
索引更新
所有的索引,以后增删改数据都需要记得维护它,为了保障原子性可以用lua。当然官方也提出,网络分区等各种问题会造成索引不一致,需要定时检查、全量、增量更新索引中的数据。
参考:
https://redis.io/topics/indexes