redis总结

官方文档:官方中文文档

目录:

  1. 入门
    1. 简介
    2. 安装
    3. 配置
    4. 基本数据类型
    5. redis命令
    6. redis中以层级关系、目录形式存储数据
  2. 专题功能
    1. 事务
    2. 管道
    3. Lua 脚本
    4. 慢查询日志
  3. 实用功能
    1. 缓存
    2. 发布-订阅
    3. 分布式锁
  4. 单机数据库实现
    1. 持久化
    2. 分区
  5. 多机数据库实现
    1. 复制和哨兵
    2. 集群
  6. 实用场景

知识点:

  1. 入门
    1. 简介
      Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存中的一个存储系统,你可以把它作为数据库,缓存和消息中间件来使用。同时支持strings,lists,hashes,sets,sorted sets,bitmaps,hyperloglogs和geospatial indexes等数据类型。它还内建了复制,lua脚本,LRU,事务等功能,通过redis sentinel实现高可用,通过redis cluster实现了自动分片。以及事务,发布/订阅,自动故障转移等等。
    2. 安装
      下载、安装、启动:无需停机升级或重启 Redis 实例
    3. 配置
      Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf
      1. Redis为什么默认有16个数据库:
        Redis默认支持16个数据库,可以通过调整Redis的配置文件redis/redis.conf中的databases来修改这一个值,设置完毕后重启Redis便完成配置。
        注意,Redis集群下只有db0,不支持多db。
        一般一个应用程序对应一个redis实例,而不是对应一个redis中的数据库。
    4. 数据类型
      string:最基本的数据类型,二进制安全的字符串,最大512M。
      list:按照添加顺序保持顺序的字符串列表。
      set:无序的字符串集合,不存在重复的元素。
      sorted set:已排序的字符串集合。
      hash:key-value对的一种集合。
      bitmap:更细化的一种操作,以bit为单位。
      hyperloglog:是用来做基数统计的算法
    5. redis命令
      启动、关闭命令
      设置密码命令
      选择数据库:select number
      key命令
      5种数据类型基本命令
    6. redis中以层级关系、目录形式存储数据
      1. 对于每种数据类型都可以多层目录存储
        例:String类型
        redis总结_第1张图片
        redis总结_第2张图片
        例:hash类型
        redis总结_第3张图片
        redis总结_第4张图片
    7. Redis写入和读取对象数据的两种方式:对象实现序列化,使用对象流进行字节储存和使用gson工具包将对象转换为json储存
      gson的基本使用
    8. 本部分重要知识
      1. 过期(Expires):Redis允许为每一个key设置不同的过期时间,当它们到期时将自动从服务器上删除。
        1.expire key time
        将key的过期时间设为time。
        2.persist key
        使用PERSIST命令可以清除超时,使其变成一个永久的key。
        3.TTL key
        返回key的过期时间
        4.SETEX key seconds value
        只能设置字符串的过期时间 ,并将 key 的过期时间设为 seconds (以秒为单位)。
        5.SETNX key value
        只有在 key 不存在时设置 key 的值。
        注意:4.5用在分布式锁中
        1. Redis如何淘汰过期的keys:Redis keys过期有两种方式:被动和主动方式。
          1. 被动:超时后只有对key执行DEL命令或者SET命令或者GETSET时才会清除。 这意味着,从概念上讲所有改变key的值的操作都会使他清除。 例如,INCR递增key的值,执行SET操作、执行LPUSH操作、执行SADD操作、执行ZADD操作或者用HSET改变hash的field所有这些操作都会触发删除动作。
          2. 主动:当然,这样是不够的,因为有些过期的keys,永远不会访问他们。 无论如何,这些keys应该过期,所以定时随机测试设置keys的过期时间。所有这些过期的keys将会从密钥空间删除。
            具体就是Redis每秒10次做的事情:
            1. 测试随机的20个keys进行相关过期检测。
            2. 删除所有已经过期的keys。
            3. 如果有多于25%的keys过期,重复步奏1.
  2. 专题功能
    1. Redis 事务:将一组命令放在同一个事务中进行处理。
      上述数据类型中,每一个数据类型都有独立的命令来进行操作,很多情况下我们需要一次执行不止一个命令,而且需要其同时成功或者失败。redis对事务的支持也是源自于这部分需求,即支持一次性按顺序执行多个命令的能力,并保证其原子性。
    2. 管道:学习如何一次发送多个命令,节省往返时间。
      因为redis的客户端和服务器的连接时基于请求-响应式协议的TCP服务的,所以当客户端请求发出,服务端处理并返回结果到客户端,一般是以阻塞形式等待服务端的响应,也就是说默认每次连接都时只能执行一个命令。管道则是允许利用一次连接来处理多条命令,从而可以节省一些tcp连接的开销。管道和事务的差异在于管道是为了节省通信的开销,但是并不会保证原子性。

      比如:同步数据库数据到Redis缓存数据库,缓存用户数据提高登录速度,目的是为提高速度降低数据库的IO操作频次,以及降低服务器的压力,也就是我们常说的使用Redis缓存数据库需求(这里我们以Mysql数据库为例说明)。
      https://blog.csdn.net/why_2012_gogo/article/details/51260264
    3. Redis Lua 脚本
      在事务的基础上,如果我们需要在服务端一次性的执行更复杂的操作(包含一些逻辑判断),则lua就可以排上用场了(比如在获取某一个缓存的时候,同时延长其过期时间)。redis保证lua脚本的原子性,一定的场景下,是可以代替redis提供的事务相关的命令的。相当于基于网络应用的架构风格中介绍到的远程求值(Remote Evluation = REV)的具体实现。
    4. 慢查询日志
  3. 实用功能
    1. 缓存:将Redis当做使用LRU算法的缓存来使用:如何配置并且将Redis当做缓存来使用,通过限制内存及自动回收键
      1. 第一步设置内存大小
      2. 第二步设置回收策略:当使用内存大于设置内存,就会采取回售策略进行回收
        常用的回收策略有:
        1. noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
        2. allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
        3. volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
        4. allkeys-random: 回收随机的键使得新添加的数据有空间存放。
        5. volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
        6. volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。

          说明:
          如果没有键满足回收的前提条件的话,策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了。
          选择正确的回收策略是非常重要的,这取决于你的应用的访问模式,不过你可以在运行时进行相关的策略调整,并且监控缓存命中率和没命中的次数,通过RedisINFO命令输出以便调优。
          
          一般的经验规则:
          
          使用allkeys-lru策略:当你希望你的请求符合一个幂定律分布,也就是说,你希望部分的子集元素将比其它其它元素被访问的更多。如果你不确定选择什么,这是个很好的选择。.
          使用allkeys-random:如果你是循环访问,所有的键被连续的扫描,或者你希望请求分布正常(所有元素被访问的概率都差不多)。
          使用volatile-ttl:如果你想要通过创建缓存对象时设置TTL值,来决定哪些对象应该被过期。
          allkeys-lru 和 volatile-random策略对于当你想要单一的实例实现缓存及持久化一些键时很有用。不过一般运行两个实例是解决这个问题的更好方法。
          
          为了键设置过期时间也是需要消耗内存的,所以使用allkeys-lru这种策略更加高效,因为没有必要为键取设置过期时间当内存有压力时。
    2. Redis 发布/订阅(Pub/Sub):redis是一个快速、稳定的发布/订阅的信息系统。
    3. 分布式锁
      可靠性
      首先,想要保证分布式锁可以使用,下面这四个条件是必须要满足的:
      1、互斥性。在任意时刻,只有一个客户端能持有锁。
      2、不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
      3、具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
      4、解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

      官方推荐采用Redlock算法,即使用string类型,加锁的时候给的一个具体的key,然后设置一个随机的值;取消锁的时候用使用lua脚本来先执行获取比较,然后再删除key。具体的命令如下:
      分布式锁
      SET resource_name my_random_value NX PX 30000
      if redis.call("get",KEYS[1]) == ARGV[1] then
        return redis.call("del",KEYS[1])
      else
        return 0
      end
  4. 单机数据库的实现
    1. 持久化(Persistence):了解如何配置redis的持久化。
      redis的持久化指的是redis会把内存的中的数据写入到硬盘中,在redis重新启动的时候加载这些数据,从而最大限度的降低缓存丢失带来的影响。
      Redis持久化的原理及优化:http://www.redis.cn/topics/persistence.html
      1. rdb持久化(又叫快照方式)
      2. aof持久化
      3. 两者相互合作及优缺点
    2. 分区(Partitioning):如何将你的数据分布在多个Redis里面。
  5. 多机数据库的实现
    1. 哨兵(Sentinel)和复制(Replication)
      edis服务器毫无征兆的罢工是个麻烦事。那么怎么办?答曰:备份一台,你挂了它上。那么如何得知某一台redis服务器挂了,如何切换,如何保证备份的机器是原始服务器的完整备份呢?这时候就需要Sentinel和Replication出场了。Sentinel可以管理多个Redis服务器,它提供了监控,提醒以及自动的故障转移的功能;Replication则是负责让一个Redis服务器可以配备多个备份的服务器。Redis也是利用这两个功能来保证Redis的高可用的。此外,Sentinel功能则是对Redis的发布和订阅功能的一个利用
      1. 复制:http://www.redis.cn/topics/replication.html
        1.设置主从复制的步骤
        2.Redis 全量复制和部分复制详解
      2. 哨兵:http://www.redis.cn/topics/sentinel.html
        哨兵(Sentinel):Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
        1. 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
          1. 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
          2. 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

            Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。
            虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器, 你可以在启动一个普通 Redis 服务器时通过给定 –sentinel 选项来启动 Redis Sentinel 。
          3. sentinel操作(windows实现):https://blog.csdn.net/liuchuanhong1/article/details/53206028
    2. 集群:http://www.redis.cn/documentation.html
      单台服务器资源的总是有上限的,CPU资源和IO资源我们可以通过主从复制,进行读写分离,把一部分CPU和IO的压力转移到从服务器上。但是内存资源怎么办,主从模式做到的只是相同数据的备份,并不能横向扩充内存;单台机器的内存也只能进行加大处理,但是总有上限的。所以我们就需要一种解决方案,可以让我们横向扩展。最终的目的既是把每台服务器只负责其中的一部分,让这些所有的服务器构成一个整体,对外界的消费者而言,这一组分布式的服务器就像是一个集中式的服务器一样(之前在解读REST的博客中解释过分布式于基于网络的差异:基于网络应用的架构)。
      在Redis官方的分布式方案出来之前,有twemproxy和codis两种方案,这两个方案总体上来说都是依赖proxy来进行分布式的,也就是说redis本身并不关心分布式的事情,而是交由twemproxy和codis来负责。而redis官方给出的cluster方案则是把分布式的这部分事情做到了每一个redis服务器中,使其不再需要其他的组件就可以独立的完成分布式的要求。我们这里不关心这些方案的优略,我们关注一下这里的分布式到底是要处理那些事情?也就是twemproxy和codis独立处理的处理分布式的这部分逻辑和cluster集成到redis服务的这部分逻辑到底在解决什么问题?
      如我们前面所说的,一个分布式的服务在外界看来就像是一个集中式的服务一样。那么要做到这一点就面临着有一个问题需要解决:既是增加或减少分布式服务中的服务器的数量,对消费这个服务的客户端而言应该是无感的;那么也就意味着客户端不能穿透分布式服务,把自己绑死到某一个台的服务器上去,因为一旦如此,你就再也无法新增服务器,也无法进行故障替换。
      解决这个问题有两个路子:
      第一个路子最直接,那就是我加一个中间层来隔离这种具体的依赖,即twemproxy采用的方式,让所有的客户端只能通过它来消费redsi服务,通过它来隔离这种依赖(但是你会发现twermproxy会成为一个单点),这种情况下每台redis服务器都是独立的,它们之间彼此不知对方的存在;

      第二个路子是让redis服务器知道彼此的存在,通过重定向的机制来引导客户端来完成自己所需要的操作,比如客户端链接到了某一个redis服务器,说我要执行这个操作,redis服务器发现自己无法完成这个操作,那么就把能完成这个操作的服务器的信息给到客户端,让客户端去请求另外的一个服务器,这时候你就会发现每一个redis服务器都需要保持一份完整的分布式服务器信息的一份资料,不然它怎么知道让客户端去找其他的哪个服务器来执行客户端想要的操作呢。
      上面这一大段解释了这么多,不知有没有发现不管是第一个路子还是第二个路子,都有一个共同的东西存在,那就是分布式服务中所有服务器以及其能提供的服务的信息。这些信息无论如何也是要存在的,区别在于第一个路子是把这部分信息单独来管理,用这些信息来协调后端的多个独立的redis服务器;第二个路子则是让每一个redis服务器都持有这份信息,彼此知道对方的存在,来达成和第一个路子一样的目的,优点是不再需要一个额外的组件来处理这部分事情。
      Redis Cluster的具体实现细节则是采用了Hash槽的概念,即预先分配出来16384个槽:在客户端通过对Key进行CRC16(key)% 16384运算得到对应的槽是哪一个;在redis服务端则是每个服务器负责一部分槽,当有新的服务器加入或者移除的时候,再来迁移这些槽以及其对应的数据,同时每个服务器都持有完整的槽和其对应的服务器的信息,这就使得服务器端可以进行对客户端的请求进行重定向处理。
      1. 集群的作用
      2. 集群原理
      3. 使用流程
      4. 实例:windows下搭建redis集群

        https://blog.csdn.net/why_2012_gogo/article/details/51463645
        https://blog.csdn.net/why_2012_gogo/article/details/51471911
        https://www.cnblogs.com/tommy-huang/p/6240083.html

      5. 总结
      6. 为什么RedisCluster采用16384个槽位?
        https://bugwz.com/2019/09/06/redis-cluster-slots-num/
      7. Redis高可用架构
        https://www.cnblogs.com/jimersylee/p/11458520.html
  6. 实用场景
    1. Java秒杀系统实战系列~基于Redis的原子操作优化秒杀逻辑
      https://juejin.im/post/5d54bcc5f265da03d211385c
    2. Redis缓存穿透,缓存击穿,缓存雪崩原因+解决方案
      https://www.cnblogs.com/midoujava/p/11277096.html
    3. 有关 Redis 缓存的一些应用场景及踩过的坑
      https://symonlin.github.io/2019/07/29/redis-1/
    4. redis缓存介绍以及常见问题浅析
      https://juejin.im/post/5d4a5989f265da03e71addb8
    5. 典型场景设计:https://www.w3cschool.cn/redis_all_about/redis_all_about-swan26wf.html
    6. Redis高级玩法:如何利用SortedSet实现多维度排序
      https://mp.weixin.qq.com/s/LpHLnmtHi35SEGiArd0Mag
    7. Redis:解决分布式高并发修改同一个Key的问题
      https://blog.51cto.com/14455981/2423578
    8. 缓存系统:用于缓解数据库的高并发压力
    9. 计数器:使用Redis原子操作,用于社交网络的转发数,评论数,粉丝数,关注数等
    10. 排行榜:使用zset数据结构,进行排行榜计算
    11. 实时系统:使用Redis位图的功能实现布隆过滤器,进而实现垃圾邮件处理系统
    12. 消息队列:使用list数据结构,消息发布者push数据,多个消息订阅者通过阻塞线程pop数据,以此提供简单的消息队列能力

你可能感兴趣的:(redis)