redis学习笔记一定义,特性,应用场景,数据结构

Redis 安装(Windows和Linux ):
https://blog.csdn.net/qq_22860341/article/details/77533372

一,初识redis


Redis是一种基于键值对(key-value)的NoSQL数据库,与很多键值对 数据库不同的是,Redis中的值可以是由string(字符串)、hash(哈希)、 list(列表)、set(集合)、zset(有序集合)、Bitmaps(位图)、 HyperLogLog、GEO(地理信息定位)等多种数据结构和算法组成,因此 Redis可以满足很多的应用场景,而且因为Redis会将所有数据都存放在内存 中,所以它的读写性能非常惊人。


与其他数据库对比:

这里写图片描述

1、redis特性


(1)速度快
正常情况下,Redis执行命令的速度非常快,官方给出的数字是读写性 能可以达到10万/秒,当然这也取决于机器的性能。
Redis速度之快,可以大致归纳为以下几点:

     ·Redis的所有数据都是存放在内存中的。
     ·Redis是用C语言实现的,一般来说C语言实现的程序“距离”操作系统更近,执行速度相对会更快。
     ·Redis使用了单线程架构,预防了多线程可能产生的竞争问题

(2)基于键值对的数据结构服务器

Redis中的值不仅可以是字符串,而且还可以是具体的数据结构,这样不仅能便于在许多应用场景的开发,同时也能够提高开 发效率。Redis的全称是REmote Dictionary Server,它主要提供了5种数据结构:字符串、哈希、列表、集合、有序集合,同时在字符串的基础之上演变 出了位图(Bitmaps)和HyperLogLog两种神奇的“数据结构”。


(3) 丰富的功能

除了5种数据结构,Redis还提供了许多额外的功能:

·提供了键过期功能,可以用来实现缓存。
·提供了发布订阅功能,可以用来实现消息系统。
·支持Lua脚本功能,可以利用Lua创造出新的Redis命令。
·提供了简单的事务功能,能在一定程度上保证事务特性。
·提供了流水线(Pipeline)功能,这样客户端能将一批命令一次性传到 Redis,减少了网络的开销。
......
......

(4)简单稳定

Redis的简单主要表现在三个方面:

首先,Redis的源码很少,早期版本 的代码只有2万行左右,3.0版本以后由于添加了集群特性,代码增至5万行 左右,相对于很多NoSQL数据库来说代码量相对要少很多,也就意味着普通 的开发和运维人员完全可以“吃透”它。其次,Redis使用单线程模型,这样 不仅使得Redis服务端处理模型变得简单,而且也使得客户端开发变得简 单。最后,Redis不需要依赖于操作系统中的类库(例如Memcache需要依赖 libevent这样的系统类库),Redis自己实现了事件处理的相关功能。


(5)客户端语言多

Redis提供了简单的TCP通信协议,很多编程语言可以很方便地接入到 Redis,并且由于Redis受到社区和各大公司的广泛认可,所以支持Redis的客 户端语言也非常多,几乎涵盖了主流的编程语言,例如Java、PHP、 Python、C、C++、Nodejs。。。


(6)持久化

将数据放在内存中是不安全的,一旦发生断电或者机器故障, 重要的数据可能就会丢失,因此Redis提供了两种持久化方式:RDB和 AOF,即可以用两种策略将内存的数据保存到硬盘中(如图1-1所示),这 样就保证了数据的可持久性。


(7)主从复制

Redis提供了复制功能,实现了多个相同数据的Redis副本(如图1-2所 示),复制功能是分布式Redis的基础。


(8)高可用和分布式

Redis从2.8版本正式提供了高可用实现Redis Sentinel,它能够保证Redis 节点的故障发现和故障自动转移。Redis从3.0版本正式提供了分布式实现 Redis Cluster,它是Redis真正的分布式实现,提供了高可用、读写和容量的
扩展性。


二、Redis使用场景



1,缓存

缓存机制几乎在所有的大型网站都有使用,合理地使用缓存不仅可以加 快数据的访问速度,而且能够有效地降低后端数据源的压力。Redis提供了键值过期时间设置,并且也提供了灵活控制最大内存和内存溢出后的淘汰策略。


2.排行榜系统

排行榜系统几乎存在于所有的网站,例如按照热度排名的排行榜,按照 发布时间的排行榜,按照各种复杂维度计算出的排行榜,Redis提供了列表
和有序集合数据结构,合理地使用这些数据结构可以很方便地构建各种排行
榜系统。


3.计数器应用

计数器在网站中的作用至关重要,例如视频网站有播放数、电商网站有 浏览数,为了保证数据的实时性,每一次播放和浏览都要做加1的操作,如 果并发量很大对于传统关系型数据的性能是一种挑战。Redis天然支持计数功能而且计数的性能也非常好,可以说是计数器系统的重要选择。

Redis的命令都是原子性的,你可以轻松地利用 INCR,DECR命令来构建计数器系统


4.社交网络

赞/踩、粉丝、共同好友/喜好、推送、下拉刷新等是社交网站的必备功能,由于社交网站访问量通常比较大,而且传统的关系型数据不太适合保存 这种类型的数据Redis提供的数据结构可以相对比较容易地实现这些功能。


5.消息队列系统

消息队列系统可以说是一个大型网站的必备基础组件,因为其具有业务 解耦、非实时业务削峰等特性。Redis提供了发布订阅功能和阻塞队列的功能,虽然和专业的消息队列比还不够足够强大,但是对于一般的消息队列功能基本可以满足。

使用 list可以构建队列系统,使用 sorted set甚至可以构建有优先级的队列系统


6,取最新 N个数据的操作

比如典型的取你网站的最新文章,通过下面方式,我们可以将最新的 5000条评论的 ID放在Redis的 List集合中,并将超出集合部分从数据库获取。

使用 LPUSH latest.comments<ID>命令,向 list集合中插入数据
插入完成后再用 LTRIM latest.comments 0 5000命令使其永远只保存最近  5000个    ID
然后我们在客户端获取某一页评论时可以用下面的逻辑
FUNCTION get_latest_comments(start,num_items):
id_list = redis.lrange("latest.comments",start,start+num_items-1)
IF id_list.length < num_items
id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")
END
RETURN id_list



7,需要精准设定过期时间的应用

比如你可以把上面说到的 sorted set的 score值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序,定时清除过期数据了,不仅是清除 Redis中的过期数据,你完全可以把 Redis里这个过期时间当成是对数据库中数据的索引,用 Redis来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录。


8,Uniq操作,获取某段时间所有数据排重值

这个使用 Redis的 set数据结构最合适了,只需要不断地将数据往 set中扔就行了,set意为
集合,所以会自动排重。


三,redis的五种数据结构


redis可以存储键和五种不同类型的值之间的映射
String字符串
List列表
Set集合
Hash散列
Zset有序集合

这里写图片描述


String字符串

string是最简单的类型,你可以理解成与 Memcached是一模一样的类型,一个 key对应一个value,其上支持的操作与 Memcached的操作类似。但它的功能更丰富。

string类型是二进制安全的,因为它本质上就是个 byte数组,当然可以包含任何数据了。

意思是 redis的 string可以包含任何数据,比如 jpg图片或者序列化的对象,值最大不能超过512MB。

string 类型的定义:

struct sdshdr {

    int len; //len表示buf中存储的字符串的长度。

    int free; //free表示buf中空闲空间的长度。

    char buf[]; //buf用于存储字符串内容。

};

len 是 buf 数组的长度。

free 是数组中剩余可用字节数,由此可以理解为什么 string 类型是二进制安全的了,因为它 本质上就是个 byte 数组,当然可以包含任何数据了 buf 是个 char 数组用于存贮实际的字符串内容,其实 char 和 c#中的 byte 是等价的,都是一 个字节。

 (1)内部编码
 字符串类型的内部编码有3种:

·int8个字节的长整型。

·embstr:小于等于39个字节的字符串。

·raw:大于39个字节的字符串。

Redis会根据当前值的类型和长度决定使用哪种内部编码实现。

查看内部编码

object encoding key

(2)常用命令

常用String命令大全请参考:

http://doc.redisfans.com/string/index.html


(3)应用场景

常规key-value缓存应用。string类型是二进制类型,可以将图片和视屏,等等保存起来,也可以将一些静态文件保存起来,如js、css等等,常规计数: 微博数, 粉丝数,共享Session,限制登录次数,发送短信验证码次数等。

例如:(共享Session)

一个分布式Web服务将用户的Session信息(例如用户登录信息)保存在各自服务器中,这样会造成一个问题,出于负载衡的考虑,分布式服务会将用户的访问均衡到不同服务器上,用户刷新一次访问可能会发现需要重新登录。

为了解决这个问题,可以使用Redis将用户的Session进行集中管理,在这种模式下只要保证Redis是高可用和扩展性的,每次用户更新或者查询登录信息都直接从Redis中集中获取。


限速:

很多应用出于安全的考虑,会在每次进行登录时,让用户输入手机验证码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制用户每分钟获取验证码的频率,例如一分钟不能超过5次。
此功能可以使用Redis来实现,下面的伪代码给出了基本实现思路:

phoneNum = "18380475489";
key = "shortMsg:limit:" + phoneNum;
// SET key value EX 60 NX
isExists = redis.set(key,1,"EX 60","NX");
if(isExists != null || redis.incr(key) <=5){
     // 通过
}else{
    // 限速
}

Hash类型

hash是一个string类型的field和value的映射表,它的添加,删除操作都是O(1),hash特别适合用于存储对象。 相较于将对象的每个字段存成单个string类型,将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。

Redis键值对和哈希类型二者的关系可以用下图表示:
这里写图片描述

哈希类型中的映射关系叫作field-value,注意这里的value是指field对应的值,不是键对应的值,请注意value在不同上下文的作用。


hash命令大全

http://doc.redisfans.com/hash/index.html


内部编码

哈希类型的内部编码有两种:

·ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。

hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

(1)当field个数比较少且没有大的value时,内部编码为ziplist

(2)当有value大于64字节,内部编码会由ziplist变为hashtable

(3)当field个数超过512,内部编码也会由ziplist变为hashtable


Hash使用场景

使用哈希类型缓存用户信息:

这里写图片描述

相比于使用字符串序列化缓存用户信息,哈希类型变得更加直观,并且在更新操作上会更加便捷。可以将每个用户的id定义为键后缀,多对field-value对应每个用户的属性.

类似如下伪代码:

UserInfo getUserInfo(long id){
    // 用户id作为key后缀
    userRedisKey = "user:info:" + id;
    // 使用hgetall获取所有用户信息映射关系
    userInfoMap = redis.hgetAll(userRedisKey);
    UserInfo userInfo;
    if (userInfoMap != null) {
        // 将映射关系转换为UserInfo
        userInfo = transferMapToUserInfo(userInfoMap);
    } else {
        // 从MySQL中获取用户信息
        userInfo = mysql.get(id);
        // 将userInfo变为映射关系使用hmset保存到Redis中
        redis.hmset(userRedisKey, transferUserInfoToMap(userInfo));
        // 添加过期时间
        redis.expire(userRedisKey, 3600);
    }
    return userInfo;
}

到目前为止,我们已经能够用三种方法缓存用户信息,下面给出三种方案的实现方法和优缺点分析。

1)原生字符串类型:每个属性一个键

set user:1:name tom
set user:1:age 23
set user:1:city beijing

优点:简单直观,每个属性都支持更新操作

缺点:占用过多的键,内存占用量较大,同时用户信息内聚性比较差,所以此种方案一般不会在生产环境使用。


2)序列化字符串类型:将用户信息序列化后用一个键保存。

set user:1 serialize(userInfo)

优点:简化编程,如果合理的使用序列化可以提高内存的使用效率

缺点:序列化和反序列化有一定的开销,同时每次更新属性都需要把全部数据取出进行反序列化,更新后再序列化到Redis中

3)哈希类型:每个用户属性使用一对field-value,但是只用一个键保存。

hmset user:1 name tomage 23 city beijing

优点:简单直观,如果使用合理可以减少内存空间的使用。

缺点:要控制哈希在ziplist和hashtable两种内部编码的转换,hashtable会消耗更多内存。


List

列表(list)类型是用来存储多个有序的字符串,a、b、c、d、e五个元素从左到右组成了一个有序的列表,列表中的每个字符串称为元素(element),一个列表最多可以存储232-1个元素。在Redis中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。


列表两端插入和弹出操作

这里写图片描述


列表类型有两个特点:

第一、列表中的元素是有序的,这就意味着可以通过索引下标获取某个元素或者某个范围内的元素列表.

第二、列表中的元素可以是重复的.

list命令大全

http://doc.redisfans.com/list/index.html

这里写图片描述

列表的四种操作类型:

这里写图片描述

列表命令时间复杂度:

这里写图片描述


内部编码

列表类型的内部编码有两种。

·ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。

·linkedlist(链表):当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。


下面的示例演示了列表类型的内部编码,以及相应的变化:

1)当元素个数较少且没有大元素时,内部编码为ziplist:

127.0.0.1:6379> rpush listkey e1 e2 e3
(integer) 3
127.0.0.1:6379> object encoding listkey
"ziplist"

2)当元素个数超过512个,内部编码变为linkedlist:

127.0.0.1:6379> rpush listkey e4 e5 ...忽略... e512 e513
(integer) 513
127.0.0.1:6379> object encoding listkey
"linkedlist"

3)或者当某个元素超过64字节,内部编码也会变为linkedlist:

127.0.0.1:6379> rpush listkey "one string is bigger than 64 byte...............
    ................."
(integer) 4
127.0.0.1:6379> object encoding listkey
"linkedlist"

使用场景


1,消息队列系统

使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。

比如:将Redis用作日志收集器


实际上还是一个队列,多个端点将日志信息写入Redis,然后一个worker统一将所有日志写到磁盘


取最新N个数据的操作

记录前N个最新登陆的用户Id列表,超出的范围可以从数据库中获得

//把当前登录人添加到链表里
ret = r.lpush("login:last_login_times", uid)

//保持链表只有N位
ret = redis.ltrim("login:last_login_times", 0, N-1)

//获得前N个最新登陆的用户Id列表
last_login_list = r.lrange("login:last_login_times", 0, N-1)

比如sina微博:

在Redis中我们的最新微博ID使用了常驻缓存,这是一直更新的。但是我们做了限制不能超过5000个ID,因此我们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。

我们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了


2,文章列表

每个用户有属于自己的文章列表,现需要分页展示文章列表。此时可以考虑使用列表,因为列表不但是有序的,同时支持按照索引范围获取元素

Redis消息队列模型

这里写图片描述

实际上列表的使用场景很多,在选择时可以参考以下口诀:

·lpush+lpop=Stack(栈)
·lpush+rpop=Queue(队列)
·lpsh+ltrim=Capped Collection(有限集合)
·lpush+brpop=Message Queue(消息队列)

set集合

集合(set)类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。如下图所示,集合user:1:follow包含着”it”、”music”、”his”、”sports”四个元素,一个集合最多可以存储232-1个元素。Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集,合理地使用好集合类型,能在实际开发中解决很多实际问题。

这里写图片描述


set命令大全

http://doc.redisfans.com/set/index.html

集合常用命令时间复杂度

这里写图片描述


内部编码

集合类型的内部编码有两种:

·intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。

·hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。


下面用示例来说明:

1)当元素个数较少且都为整数时,内部编码为intset:

127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 4
127.0.0.1:6379> object encoding setkey
"intset"

2)当元素个数超过512个,内部编码变为hashtable:

127.0.0.1:6379> sadd setkey 1 2 3 4 5 6 ... 512 513
(integer) 509
127.0.0.1:6379> scard setkey
(integer) 513
127.0.0.1:6379> object encoding listkey
"hashtable"

3)当某个元素不为整数时,内部编码也会变为hashtable:

127.0.0.1:6379> sadd setkey a
(integer) 1
127.0.0.1:6379> object encoding setkey
"hashtable"

使用场景

Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

Set 就是一个集合,集合的概念就是一堆不重复值的组合。利用Redis提供的Set数据结构,可以存储一些集合性的数据。


1,在微博应用
案例:

在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。

Set是集合,是String类型的无序集合,set是通过hashtable实现的,概念和数学中个的集合基本类似,可以交集,并集,差集等等,set中的元素是没有顺序的。


2,集合类型比较典型的使用场景是标签(tag)

例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣点就是标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同喜好的标签,这些数据对于用户体验以及增强用户黏度比较重要。例如一个电子商务的网站会对不同标签的用户做不同类型的推荐,比如对数码产品比较感兴趣的人,在各个页面或者通过邮件的形式给他们推荐最新的数码产品,通常会为网站带来更多的利益。
下面使用集合类型实现标签功能的若干功能。

(1)给用户添加标签

sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
 ...
sadd user:k:tags tag1 tag2 tag4
...

(2)给标签添加用户

sadd tag1:users user:1 user:3
sadd tag2:users user:1 user:2 user:3
...
sadd tagk:users user:1 user:2

(3)删除用户下的标签

srem user:1:tags tag1 tag5
...

(4)删除标签下的用户

srem tag1:users user:1
srem tag5:users user:1
...

(3)和(4)也是尽量放在一个事务执行。

(5)计算用户共同感兴趣的标签

可以使用sinter命令,来计算用户共同感兴趣的标签,如下代码所示:

sinter user:1:tags user:2:tags

有序集合Sorted Set

有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据。如下图所示,该有序集合包含kris、mike、frank、tim、martin、tom,它们的分数分别是1、91、200、220、250、251,有序集合提供了获取指定分数和元素范围查询、计算成员排名等功能合理的利用有序集合,能帮助我们在实际开发中解决很多问题。

这里写图片描述

给出了列表、集合和有序集合三者的异同点。

这里写图片描述


命令大全Sorted Set

http://doc.redisfans.com/sorted_set/index.html

有序集合命令的时间复杂度

这里写图片描述


内部编码

有序集合类型的内部编码有两种:

·ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用。

·skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降。


下面用示例来说明:

1)当元素个数较少且每个元素较小时,内部编码为skiplist:

127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3
(integer) 3
127.0.0.1:6379> object encoding zsetkey
"ziplist"

2)当元素个数超过128个,内部编码变为ziplist:

127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3 12 e4 ...忽略... 84 e129
(integer) 129
127.0.0.1:6379> object encoding zsetkey
"skiplist"

3)当某个元素大于64字节时,内部编码也会变为hashtable:

127.0.0.1:6379> zadd zsetkey 20 "one string is bigger than 64 byte.............
    ..................."
(integer) 1
127.0.0.1:6379> object encoding zsetkey
"skiplist"

使用场景

Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。

和Set相比,Sorted Set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列,比如一个存储全班同学成绩的Sorted Set,其集合value可以是同学的学号,而score就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。另外还可以用Sorted Set来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

实现方式:

Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单


有序集合比较典型的使用场景就是排行榜系统。例如视频网站需要对用户上传的视频做排行榜,榜单的维度可能是多个方面的:按照时间、按照播放数量、按照获得的赞数。本节使用赞数这个维度,记录每天用户上传视频的排行榜。

主要需要实现以下4个功能。

(1)添加用户赞数
例如用户mike上传了一个视频,并获得了3个赞,可以使用有序集合的zadd和zincrby功能:

zadd user:ranking:2016_03_15 mike 3
如果之后再获得一个赞,可以使用zincrbyzincrby user:ranking:2016_03_15 mike 1

(2)取消用户赞数

由于各种原因(例如用户注销、用户作弊)需要将用户删除,此时需要将用户从榜单中删除掉,可以使用zrem。例如删除成员tom:

zrem user:ranking:2016_03_15 mike

(3)展示获取赞数最多的十个用户此功能使用zrevrange命令实现:

zrevrangebyrank user:ranking:2016_03_15 0 9 

(4)展示用户信息以及用户分数

此功能将用户名作为键后缀,将用户信息保存在哈希类型中,至于用户的分数和排名可以使用zscore和zrank两个功能:

hgetall user:info:tom
zscore user:ranking:2016_03_15 mike
zrank user:ranking:2016_03_15 mike

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_22860341/article/details/80255900
今日推荐