Redis深度历险 ,核心原理与应用实践
授人以鱼不如授人以渔
Redis 可以做什么?
- 记录帖子的点赞数、评论数和点击数( hash )。
- 记录用户的帖子 ID 列表(排序〉,便于快速显示用户的帖子列表( zset )。
- 记录帖子的标题、摘要、作者和封面信息, 用于列表页展示( hash )。
- 记录帖子的点赞用户 ID 列表,评论 ID 列表,用于显示和去重计数( zset )。
- 缓存近期热帖内容(帖子内窑的空间占用比较大),减少数据库压力( hash )。
- 记录帖子的相关文章 ID ,根据内容推荐相关帖子 (list) 。
- 如果帖子 ID 是整数自增的,可以使用 Redis 来分配帖子 ID (计数器)。
- 收藏集和帖子之间的关系(zset)。
- 记录热榜帖子 ID 列表、总热榜和分类热榜( zset )。
- 缓存用户行为历史,过滤恶意行为( zset, hash )。
上述情况 ,适用在数据请求压力很大的时候。
万丈高楼平地起——Redis基础数据结构
5种基础数据结构
String(字符串) ,list (列表),hash(字典),set( 集合),zset (有序列表).
String:
string内部就是一个字符数组,相当于java里面的ArrayList。Redis所有的数据结构都以唯一的key字符串作为名称,然后通过这个唯一的key值来获取相应的value值。不同类型的数据结构差异在于value结构不一样。
缓存用户信息的过程:将用户信息结构体使用JSON序列化成字符串,之后将序列号的字符串塞进Redis缓存,取用户信息会经过一次反序列化过程。
常用命令:
set
key value exists
key del
key get
key
mget
key1 key2 key3 mset
key1 value key2 value key3 value
过期和 set 命令扩展
expire
key 5 #5s 后过期 setex
key 5 value # 5s 后过期,等价 set+expire
setnx
key value #如果 key不存在就执行set 创建
计数
如果 value 值是一个整数,还可以对它进行自增操作。自增的范围在 signed long 最大值和最小值之间,超出了这个范围, Redis会报错。
incrby
key number
9223372036854775807 #Long.Max
list
Redis 的列表相当于 Java 语言里面的 LinkedList。Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串,塞进 Redis 的列表,另 一个线程从这个列表中轮询数据进行处理。
右边进左边出:队列 先进先出
右边进右边出:栈 先进后出 与队列相反,使用场景不多。
慢操作
lindex
相当于 Java 链表的 get(int index 方法,对链表进行遍历,性能随index增大而变差,ltrim 来实现一个定长的链表,两个参数 start_ index 和end_ index 定义了 一个区间,在这个区间内的值 ltrim 保留
rpush
key value1 value2 value3 lrange
key 0 -1 #获取所有元素, O(n )慎用
ltrim
books 1 0 OK #这其实是清空了整个列表 因为区间范围长度为负
快速列表
Redis 底层存储是"快速链表"(quicklist)的一个结构。
首先在列表元素较少的情况下,会使用一块连续的内存储存,是压缩列表(ziplist),Redis 将链表和 ziplist 结合起来组成了 quicklist ,也就是将多个 ziplist 使用双向指针串起来使用。quicklist满足了快速的插入删除性能,不会出现太大的空间冗余。
hash
Redis 的字典相当于 Java 语言里面的 HashMap(数组+链表) ,是无序字典,Redis 的字典的值只能是字符串,另外它们 rehash 的方式不一样,Redis采用了渐进式rehash策略,渐进式 rehash会在rehash的同时保留新旧两个hash结构 ,在后续的定时任务以及 hash操作指令中循序渐进地将旧hash的内容 一点点地迁移到新 hash 结构中。当搬迁完成了,就会使用新的hash结构取代。hash结构的存储消耗要高于单个字符串。
常用命令: hset
key field value #命令行的字符串如果包含空格,要用引号括起来,如果做更新操作,所以返回0
hgetall
key hlen
key hget
key field
hmset
key field1 value1 field2 value2 field3 value3 #批量 set
hincrby
key field value increment #增加
set
相当于 Java 语言里面的 HashSet,是无序的、唯一的。内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL,当集合中最后一个元素被删除时,数据结构自动被删除,内存回收。可以用于来存储在某活动中中奖的用户 ID。
常用命令: sadd
key value smembers
key sismember
key value #查询某个 value 是否存在,相当于 contains(o) scard
key #获取长度相当于 count () spop key #弹出一个
zset
它类似于Java的SortedSet和HashMap 的结合体, 保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score ,代表这个 value 的排序权重。它的内部实现用的是一种叫作“跳跃列表”的数据结构。可以用来存储粉丝列表, value值是粉丝的用户ID, score是关注时间。还可以用来存储学生的成绩,value值是学生的 ID, score 是他的考试成绩。
zadd
key score member zrange
key 0 -1 #按 score 排序列出,参数区间为排名范围
zrevrange
key 0 -1 #按 score 逆序列出,参数区间为排名范围
zcard
key #相当于 count () zscore
key value#获取指定 value的score
zrank
key value #排名 zrangebyscore
key min max #根据分值区间遍历 zset
zrem
key value #删除 value
跳跃列表
zset 内部的排序功能是通过"跳跃列表”数据结构来实现的,定位插入点时,先在顶层进行定位,然后下潜到下一级定位,一直下潜到最底层找到合适的位置,将新元素插进去。