关于redis开发详细总结

1 篇文章 1 订阅

Redis简介

  1. Redis和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)list(链表)set(集合)zset(sorted set --有序集合)和hash(哈希类型)。(五种数据类型)
  2. Redis是一个单线程程序。通过多路复用和非阻塞IO技术处理消息。(经典问题:select、poll、epoll的区别,对应于Java的NIO技术、Nginx的Node事件处理)

数据类型及使用场景

Redis数据类型: String

  • 常用命令
    除了get、set、incr、decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一段内容 设置及获取字符串的某一位(bit) 批量设置一系列字符串的内容
  1. 使用场景1:计数器
    比如统计日PV,假定 key 为 pv:yyyyMMdd:somePage,则每当有页面访问时,调用 incr pv:yyyyMMdd:somePage,其中 yyyyMdd 为具体某个日期。
  2. 使用场景2:有时效的缓存
    如果 session 过期时间为30分钟,可以根据 sessionId 缓存相关信息,当用户首次访问时用命令 set sessionId someValue EX 1800,其中 EX 1800表示30分钟后过期,每当用户有操作时,一般需要更新 session 过期时间,此时用命令 expire sessionId 1800 即可。
    当然,redis 中所有类型的 key 都可以设置时效,string 数据类型只是其中一种。
  3. 使用场景3:位图
    假定用户 ID 从0开始自然增长,需要统计用户的月度活跃度,则可以每天有一个key,key 的第0个字符为1表示用户当天活跃,为0则不活跃,这样某天的活跃信息可以用命令 setbit daily:active:users:yyyyMMdd offset 1,这样求月度活跃用户首先可以用命令 bitop OR monthly:active:users:202001 daily:active:users:20200101 daily:active:users:20200102 … daily:active:users:20200131 将结果存入 key 为 monthly:active:users:202001 的 string 中,最后调用 bitcount monthly:active:users:202001 即可得出月度活跃用户数。
    实现方式
    incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。

Redis数据类型:Hash

  • 常用命令
    hget,hset,hgetall 等。
  1. 使用场景1:作为key
    我们简单举个实例来描述下Hash的应用场景,比如我们要存储一个用户信息对象数据,包含以下信息: * Key:用户ID * Value:用户对象,包含姓名name,年龄age,生日birthday 等信息, 如果用普通的key/value结构来存储,主要有以下2种存储方式:
  • 第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,如:set u001 “李三,18,20010101” ** 这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。
  • 第二种方法是这个用户信息对象有多少成员就存成多少个key-value对,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值, 如:mset user:001:name "李三 "user:001:age18 user:001:birthday “20010101” ** 虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的
    那么Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口, 如:hmset user:001 name “李三” age 18 birthday “20010101” 也就是说,Key仍然是用户ID,value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部 Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。
    这里同时需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作, 由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而 另其它客户端的请求完全不响应,这点需要格外注意。
    实现方式
    上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用 类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转 成真正的HashMap,此时encoding为ht。

Redis数据类型: list

  • 常用命令
    lpush, rpush, lpop, rpop, lrange, blpop (阻塞版)等。
  1. 使用场景1:缓存热点数据
    在微博、论坛之类的系统中,缓存论坛首页帖子的标题,内容,并且缓存这些帖子的前 N 页回复、评论。每当首页有新帖子时,用命令 lpush firstPage "帖子ID|标题|内容将帖子|…"加入 list,再调用 ltrim firstPage 0 N-1 来确保只缓存最近 N 条数据;缓存每个帖子的回复或评论也可以用类似命令,在取数据时,用命令 lrange firstPage 0 N-1取出,最新帖子自然是第一条。
    假定需要在某页面醒目位置显示最新产品,仍然可以用 list 来实现,如果取最新3个产品用命令 lrange product:list:key 0 2。
  2. 使用场景2:消息队列
    通过 lpush 与 lpop / blpop 配合使用,实现消息队列的功能 。
  • 拓展补充:
    Redis的列表相当于Java语言中的LinkedList。但是深入一点,Redis的底层存储并不是一个简单的LinkedList,而是被称为一个快速链表**“QuickList”**的数据结构,数据量比较少的时候,以连续内存存储,称作压缩列表(ZipList)。数据量大的时候,则变成快速链表(QuickList)即链表和压缩列表的结合。

Redis数据类型: Set

Set 就是一个集合,set 中的元素无序但是不重复,利用 redis 提供的 set 数据结构,可以存储一些集合性的数据,并使用求交集、并集、差集等操作。

  • 常用命令
    sadd, srem, spop, sdiff, smembers, sunion 等。
  1. 使用场景:分析共同点
    分析用户A与用户B的共同点,如果两个人是好友,可以分析他们共同关注的产品或者其它共同行为,实现精准的广告投放或其它营销行为。关注的产品或其它行为就可以用 set 这种数据结构存放,并用 sinter 取交集。

Redis数据类型: ZSet

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

  • 常用命令
    zadd,zrange,zrem,zcard等。
  1. 使用场景:带优先级的消息系统
    某个消息处理系统,对优先级高的消息需要优先处理,可以考虑使用 sorted set,在产生消息时用命令 zadd message:queue score message,其中的score指定优先级,比如10是最高优先级,取消息时通过zrange message:queue score 10取优先级最高的消息先处理,当没有优先级为10的消息时才处理优先级比10低的消息。
  • 拓展补充:
    底层实现原理“跳跃列表”。

行内具体情况

目前行内提供两种redis部署模式,分别是:集群模式和哨兵模式

哨兵模式:

• Redis主从模式主要由一个master、两个slave和三个哨兵实例组成。主要由一个master对外提供读写服务,slave也可以配置为提供读服务。
• 哨兵用于监控Redis节点的工作状态,在主节点发生故障时,可以实现主从的切换,保证系统的高可用。
• 行内Redis主从模式,主要由三个虚拟机构成,每个虚拟机上有一个Redis进程和一个哨兵进程
• 哨兵(sentinel)是Redis 的高可用性解决方案:由一个或多个sentinel实例组成的sentinel 系统可以监视任意多个master,以及这些master的所有slave,并在被监视的master进入下线状态时,自动将下线master的某个slave升级为新的master。

集群模式:

• Redis 集群的每个虚拟机都有一主一备两个进程。其中Master用于存储数据,Slave则是其他虚拟机上Master的复制。Master和对应的Slave处于不同的虚拟机,防止1个虚拟机挂掉对Redis集群可能造成影响,不同虚拟机均匀分布在多个物理机,防止出现物理机故障导致3个虚拟机都挂掉的情况。
• 集群将整个数据库分为 16384 个槽(slot),所有键都属于这 16384 个槽的其中一个,计算键 key属于哪个槽的公式为 slot_number = crc16(key) % 16384 ,其中 crc16 为 16 位的循环冗余校验和函数。集群中的每个主节点都可以处理 0 个至 16384 个槽,当 16384 个槽都有某个节点在负责处理时,集群进入上线状态,并开始处理客户端发送的数据命令请求。

主从模式和哨兵模式对比:

  1. 组成:主从模式由1个master、2个slave和3个哨兵实例组成;集群模式由3个master和3个slave组成,并且可以动态扩展到更多节点。
  2. 数据分片:集群模式的数据分片到多个节点,由多个master同时对外提供服务,且支持线性扩容,主从模式数据没有分片,只有一个master对外提供写服务,但是可以通过访问slave节点,扩展能力。
  3. 故障转移机制:集群模式由节点之间的心跳实现故障发现和自动转移;主从模式依赖哨兵模式实现故障发现和主从切换。
  4. 高可用性:都具有主从同步和自动切换,都尽可能的分布到多个虚拟机和多个可用区,集群模式如果虚拟机数超过可用区数量,则可能存在多个节点位于同一个可用区的情况。
  5. 数据一致性:两种模式的主从同步机制一样,slave使用异步复制,不保证数据的强一致性,当master节点不可用,slave节点被提升为master时,如果有数据没有同步到,则该数据丢失。

拓展

显然,掌握以上内容是无法应对复杂的面试问题的,除了以上内容,以下为拓展场景。

  1. 分布式锁
    Setnx-expire-del指令:
    Set lock:chdehole true ex 5 nx
    但分布式锁存在一个超时问题,即任务逻辑大于设置的超时时间,这里可以采用设置随机数的方式让操作变得稍稍安全,实现需要采用lua脚本。
    模糊统计
  2. HyperLogLog
    应用场景:统计网页UV,不同于PV,一个用户对每一个页面的多次访问只算作一次。如果数量级很大,则set不合适。HyperLogLog提供一个不精确的去重计数方案,但也不是很离谱,标注误差0.81%。
    指令:pfadd,pfcount,pfmerge
    实现原理:最低位连续零位的最大长度K,该参数和随机数的数量N呈现出线性关系。
  3. 布隆过滤器
    应用场景:新闻客户端推送消息去重。布隆过滤器提供一个不那么精确的set结构,当你使用contains方法判断某个对象是否存在时,它可能会误判。
    指令:bf.add,bf.exists
    实现原理和参数选择:略
  4. 限流与漏斗算法
    应用场景: 对单用户的操作做出限制。
  5. 事务机制
    指令:multi(事务开始),exec(事务执行),discard(事务丢弃)
    Redis的事务并不具备原子性,仅仅满足了事务的隔离性中的串行化。优化:Pipeline操作将多次的IO操作压缩为单次IO操作。
    提供了一种乐观锁:watch指令(CAS机制)在multi和exec之前盯住关键变量。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值