Redis的基础

2023-05-16

Redis

文章目录

  • Redis
    • 基础
      • 和memcache的区别
      • 为什么单线程能有很高的效率
        • 具体原因
        • 连接过程
        • 一次连接流程
        • 多个socket,io多路复用程序,消息队列,文件事件分派器,事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等)
      • 哪些类型
        • string
        • list
        • hash
        • set
        • sort set
      • 从海量数据中查找某个key前缀
        • keys
        • scan
      • 持久化
        • 持久化的意义
        • rdb
        • aof
      • 序列化方式
        • JdkSerializationRedisSerializer
        • GenericJackson2JsonRedisSerializer
        • StringRedisSerializer
        • GenericFastJsonRedisSerializer
      • 数据过期/淘汰
        • 过期策略
          • 定期删除
          • 惰性删除
        • 内存淘汰机制
          • 具体策略
        • LRU代码实现
    • 思维导图
      • 博客连接
        • Redis的应用--分布式锁
        • Redis的基础
        • Redis的生产问题-缓存雪崩-缓存穿透-双写一致性--并发竞争
        • Redis的cluster集群
        • Redis的replication架构(主从+哨兵

基础

和memcache的区别

  1. 数据结构
  2. 内存使用率,key-value的话memcache更好
  3. 效率,单个value的大小100k以上redis更好
  4. 集群部署,redis有原生支持

为什么单线程能有很高的效率

具体原因

  1. 单线程模型,避免了上下文切换
  2. IO多路复用机制
  3. 纯内存操作

连接过程

文件事件处理器(网络事件处理器、file event handler),这个是单线程的采用IO多路复用机制监听多个socket。

socket进来之后,如果有事件(比如说连接),IO多路复用程序就会将这个socket(这时候连接已经和connect事件绑定) 推到消息队列中。

文件事件分派器从队列中取出socket,检查事件,根据不同的事件分给不同的处理器。

包括多个socket,io多路复用程序,消息队列,文件事件分派器,事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等)
redis的线程模型

一次连接流程

  1. 服务端打开socket监听
  2. 客户端和服务端连接socket,这时候产生一个connect事件,后台表示为AE_READABLE
  3. io多路复用程序将这个socket推到消息队列里面
  4. 分派器判断是 连接应答处理器,进行处理,连接成功
  5. 这时候将socket和ae_writeable绑定,
  6. io多路复用程序看到这个又有事件了,就又推到消息队列
  7. 分派器判断是 命令回复处理器,就返回数据,然后和这个事件取消关联

多个socket,io多路复用程序,消息队列,文件事件分派器,事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等)

哪些类型

string

  1. 字符串
  2. set key val,get key
  3. 简单的key-value存储,部门组织树,用户数据

list

  1. 数组
  2. lpush key val1 val2,lpop key,lrange key 0 10
  3. 存粉丝、评论、lrange可以分页,消息队列

hash

  1. 键值对
  2. hmset key key1 val1 key2 val2,hget key key1
  3. 用户信息-鉴权码-私钥

set

  1. 不重复无序列表
  2. sadd key val1 val2,smembers key
  3. 部门关系缓存

sort set

  1. 有序数组/带权重值列表
  2. zadd key score1 val1 score2 val2,zrangebyscore key
  3. 排行榜

从海量数据中查找某个key前缀

keys

keys pattern,

一次性返回全部满足条件数据,会阻塞redis

scan

scan cursor pattern count,

按pattern条件从下标cursor开始找count个数据,不一定会是count,大致相等。返回结果包括下一个游标位置和列表

持久化

持久化的意义

  1. 故障恢复
  2. 云备份到一个存储上

rdb

  1. 内存快照的形式
  2. RDB方式,sava 600 10,600秒内有10次写操作,则触发。
  3. 将数据快照保存,有可能丢失数据。
  4. 优点:适合做冷备份、性能(不需要每时每刻),恢复快
  5. 缺点:丢数据

aof

  1. 把所有操作指令保存下来,存到一个文件中
  2. 内存和文件中有一层os-cache,每隔1s会调用f-sync
  3. 一次只会写一个aof文件
  4. aof文件不可能无限增大,BG-REWRITE-AOF。会根据当前快照,进行重写aof文件
  5. 优点:数据丢少(1s),append-only模式写磁盘-速度快,记录是人可读的
  6. 缺点:占用磁盘大,qps写会降低,脆弱点,数据恢复比较慢

序列化方式

JdkSerializationRedisSerializer

使用JDK提供的序列化功能。 优点是反序列化时不需要提供类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。

GenericJackson2JsonRedisSerializer

StringRedisSerializer

不能序列化Bean,只能序列化字符串类型的数据,
如果value都是字符串类型,可以用该方式序列化

GenericFastJsonRedisSerializer

数据过期/淘汰

  1. 这个是缓存,有容量限制
  2. 过期之后,还是占用内存

过期策略

设置了过期时间的key什么时候删除?定期删除和惰性删除,

这2个结合起来还是有可能漏掉一些key,这时候就需要内存淘汰机制登场

定期删除

每隔100ms随机抽去一些设置了超时时间的key,检查是否过期

过期则删除

这个会导致有可能一些key已经过期,但是没有删掉

惰性删除

查询某个key的时候,惰性检查,是否过期

如果过期则返回空

内存淘汰机制

redis内存占用过多的时候,会进行内存淘汰

具体策略
  1. noeviction,报错
  2. allkeys-lru,所有key走lru算法
  3. allkeys-random,所有key走随机删除
  4. volatile-lru,设置过期时间走lru算法
  5. volatile-random,设置过期时间的key走随机删除
  6. volatile-ttl,设置过期时间的key走"按过期时间最短"的算法

LRU代码实现

链表+hashmap

add、remove、refresh用来操作链表

get、put用来提供api

lru

package com.lizhaoblog.code.io.redis;

import java.util.HashMap;

class Node {
    public Node(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public Node pre;
    public Node next;
    public String key;
    public String value;
}

public class LRUCache {
    private Node head;
    private Node end;
    //缓存上限
    private int limit;
    private HashMap<String,Node> map;

    public LRUCache(int limit) {
        this.limit = limit;
        map = new HashMap();
    }

    public String get(String key) {
        Node node = map.get(key);
        if (node == null) {
            return null;
        }
        //调整node到尾部
        refreshNode(node);
        return node.value;
    }

    public void put(String key, String value) {
        Node node = map.get(key);
        if (node == null) {
            //key不存在直接插入
            while (map.size() >= limit) {
                //去除链表内的节点
                String oldKey = removeNode(head);
                //去除map中的缓存
                map.remove(oldKey);
            }
            node = new Node(key, value);
            //链表中加入节点
            addNode(node);
            //map中加入节点
            map.put(key, node);
        } else {
            //更新节点并调整到尾部
            node.value = value;
            refreshNode(node);
        }
    }

    private void refreshNode(Node node) {
        //如果访问的是尾节点,无须移动节点
        if (node == end) {
            return;
        }
        //把节点移动到尾部,相当于做一次删除插入操作
        removeNode(node);
        addNode(node);
    }

    private String removeNode(Node node) {
        //尾节点
        if (node == end) {
            end = end.pre;
        } else if (node == head) {
            //头结点
            head = head.next;
        } else {
            //中间节点
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
        return node.key;
    }

    private void addNode(Node node) {
        if (end != null) {
            end.next = node;
            node.pre = end;
            node.next = null;
        }
        end = node;
        if (head == null) {
            head = node;
        }
    }
}

思维导图

redis的线程模型

博客连接

Redis的应用–分布式锁

Redis的应用–分布式锁

Redis的基础

Redis的基础

Redis的生产问题-缓存雪崩-缓存穿透-双写一致性–并发竞争

Redis的生产问题-缓存雪崩-缓存穿透-双写一致性–并发竞争

Redis的cluster集群

Redis的cluster集群

Redis的replication架构(主从+哨兵

Redis的replication架构(主从+哨兵)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis的基础 的相关文章

  • StackExchange.Redis 和 StackExchange.Redis.StrongName 之间有什么区别?

    当我关注Azure时文档 http azure microsoft com en us documentation articles cache dotnet how to use azure redis cache 关于如何在Azure
  • 使用 EVAL、SCAN 和 DEL 的 Redis 通配符删除脚本返回“非确定性命令后不允许写入命令”

    因此 我正在寻求构建一个 lua 脚本 该脚本使用 SCAN 根据模式查找键并删除它们 原子地 我首先准备了以下脚本 local keys local done false local cursor 0 repeat local resul
  • connect-redis - 如何保护会话对象免受竞争条件影响

    我使用 nodejs 和 connect redis 来存储会话数据 我将用户数据保存在会话中 并在会话生命周期中使用它 我注意到两个更改会话数据的请求之间可能存在竞争条件 我尝试过使用 redis lock 来锁定会话 但这对我来说有点问
  • 仅当尚未设置时才进行原子设置

    仅当尚未在 Redis 中设置时 是否有办法执行原子设置 具体来说 我正在创建一个像 myapp user user email 这样的用户 并且希望 Redis 在 user email 已被占用时返回错误 而不是默默地替换旧值 比如声明
  • PooledRedisClientManager 未释放连接

    我将 json 数据列表存储在 redis 中并使用 ServiceStack c 客户端访问它 我本质上是在管理自己的外键 我在其中存储zrangeid 我使用应用程序内部的接口从zrange然后从 Redis 获取底层 json 对象并
  • 如何让客户端下载动态生成的非常大的文件

    我有一个导出功能 可以读取整个数据库并创建一个包含所有记录的 xls 文件 然后文件被发送到客户端 当然 导出完整数据库的时间需要大量时间 并且请求很快就会以超时错误结束 处理这种情况的最佳解决方案是什么 例如 我听说过使用 Redis 创
  • WSL Redis 遇到系统尚未使用 systemd 作为 init 系统(PID 1)启动。无法操作[已关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在尝试遵循本文中讨论的 Redis 安装过程article https www digitalocean com community
  • Redis 排序集和解决关系

    我正在使用 Redis 排序集来存储我正在处理的项目的排名 我们没有预料到 我们想要如何处理关系 Redis 按字典顺序对具有相同分数的条目进行排序 但我们想要做的是对具有相同分数的所有条目给予相同的排名 例如在以下情况 redis 127
  • Redis INCRBY 有限制

    我想知道是否有一种方法可以通过我的应用程序的单次往返在 Redis 中执行此操作 对于给定的键K 其可能值V是范围内的任意整数 A B 基本上 它有上限和下限 When an INCRBY or DECRBY发出命令 例如INCRBY ke
  • Spring Data Redis JedisConnectionException:流意外结束

    雷迪斯3 0 5Spring数据Redis 1 3 6绝地武士2 6 3 我们的 Web 应用程序通过 pub sub 从 Redis 接收数据 还以键 值对的形式在 Redis 上执行数据读 写 读 写发生在监听线程 独立监控线程和htt
  • Caffeine Expiry 中如何设置多个过期标准?

    我正在使用 Caffeine v2 8 5 我想创建一个具有可变到期时间的缓存 基于 值的创建 更新以及 该值的最后一次访问 读取 无论先发生什么都应该触发该条目的删除 缓存将成为三层值解析的一部分 The key is present i
  • 通过 StackExchange.Redis 连接到 Redis Servier

    我尝试使用以下方法制作一个测试项目Redis https redis io服务器 通过 Virtual Box 安装在 Linux Ubuntu 虚拟机上 Linux 机器通过 Virtual Box 的桥接适配器与本地网络连接 Virtu
  • 如何将node.js管道传输到redis?

    我有很多数据要插入 SET INCR 到redis DB 所以我正在寻找pipeline http redis io topics pipelining 质量插入 http redis io topics mass insert通过node
  • 使用Redis从有限范围内生成唯一ID

    我有一些数据库项目 除了主键之外 还需要项目所属组的唯一索引 我们来调用属性nbr 以及将项目分组在一起并定义唯一范围的属性nbr 我们会打电话group This nbr必须在 1 N 范围内 并且may从外部源导入项目时进行设置 由于所
  • 如何在Redis中进行持久化存储?

    关闭redis服务器后 使用set存储的值被破坏 在这里我找到了使用持久性存储的方法 有人帮助我 如何使用javascript实现这一点 我想将客户端的一些值存储在 redis 数据库中 并且必须在其他客户端中使用该值 您需要配置 Redi
  • 使用 Sentinels 升级 Redis 的最佳实践?

    我有 3 个 Redis 节点 由 3 个哨兵监视 我进行了搜索 文档似乎不清楚如何最好地升级此类配置 我目前使用的是 3 0 6 版本 我想升级到最新的 5 0 5 我对这方面的程序有几个疑问 升级两个大版本可以吗 我在我们的暂存环境中执
  • 有没有办法用Lettuce自动发现Redis集群中新的集群节点IP

    我有一个Redis集群 3主3从 运行在一个库伯内斯簇 该集群通过Kubernetes 服务 Kube 服务 我将我的应用程序服务器连接到 Redis 集群 使用Kube 服务作为 URI 通过 Redis 的 Lettuce java 客
  • redis - 使用哈希

    我正在使用 redis 为我的 Web 应用程序实现社交流和通知系统 我是 redis 的新手 我对哈希值及其效率有一些疑问 我读过这篇很棒的文章Instagram 帖子 http instagram engineering tumblr
  • 有没有办法让特定的key在集群模式下定位到特定的redis实例上?

    我想让我的多锁位于不同的redis实例上 我发现redission可以指定一个实例来执行命令 但是如果该命令与key相关 则指定的实例会将命令传输到另一个实例 你能给我一些建议吗 你可以 但这并不是微不足道的 首先 Redis 在键中使用大
  • 在 Redis 上为 Django 和 Express.js 应用程序共享会话存储

    我想创建一个包含一些登录用户的 Django 应用程序 另一方面 由于我想要一些实时功能 所以我想使用 Express js 应用程序 现在的问题是 我不希望身份不明的用户访问 Express js 应用程序的日期 因此 我必须在 Expr

随机推荐