# Redis 实战读书笔记(一)

news2024/11/15 11:07:38

Redis 实战读书笔记(一)

初始Redis

Redis是一个远程内存数据库,它不仅性能强劲而且还具有复制特性以及为解决问题而生的独一无二的数据模型。Redis提供了5中不同类型的数据库,初次之外通过复制持久化和客户端分片等特性用户可以很方便的将Redis扩展成一个能够包含数百GB数据每秒处理上百万次请求的系统。

Redis 和其它数据库的对比

名称类型数据存储选项查询类型附加功能
Redis内存存储的非关系型数据库字符串、列表、散列表、集合、有序集合每种数据类型都有自己的操作命令、批量操作、事务支持发布订阅、主从复制、持久化、脚本
memcached内存存储的键值缓存键值之间的映射创建读取更新、删除等其它命令为提升性能而设的多线程服务器
mysql关系型数据库表、视图、表空间、表的行DMLACID、主从复制、主主复制
postgresql关系型数据库表、视图、表空间、表的行DMLACID、主从复制
MongoDb使用硬盘存储的非关系型文档表、表包含多个schemabson文档创建读取更新、删除等其它命令支持map-reduce、主从复制、分片、空间索引

Redis 数据结构简介

结构类型结构存储的值结构的读写能力
Strin字符串、整数或者浮点数浮点数自增或者自减
List链表链表上的每个节点包含了一个字符串链表两端推入弹出、根据偏移量进行删除…
Hash键值对的无序散列表增查删
Set包含字符串的无序收集器,并且被包含的每个字符串都是唯一的增删改查、计算交并差集…
Zset字符串成员与浮点数分值之间的有序映射,元素的排列顺序由分值大小决定增查删根据分值范围或者成员来获取元素

常用命令

字符串命令

命令作用
GET获取
SET设置
DEL删除

列表命令

命令作用
RPUSH列表右端插入
LRANGE获取列表在给定范围上的所有值
LINDEX获取列表在给定位置上的单个元素
LPOP从列表的左端弹出一个值

散列命令

命令作用
HGET获取
HSET设置
HDEL删除
HGETALL获取散列包含的所有键值对

集合命令

命令作用
SADD添加元素
SMEMBERS返回集合包含的所有元素
SISMEMBER检查给定元素是否存在于集合中
SREM如果给定的元素存在那么移除这个元素

有序集合命令

命令作用
ZADD将一个带给定分值的成员添加到有序集合里面
ZRANGE根据元素在有序排列中所处的位置从有序集合里面获取多个元素
ZRANGERBYSCORE获取有序集合在给定分值范围内的所有元素
ZREM如果给定的元素存在那么移除这个元素

使用Redis 构建Web应用

典型Web 服务器对请求进行相应的步骤

  • 服务器对客户端发来的请求进行解析
  • 请求被转发给一个预定义的处理器
  • 处理器从数据库中拿到数据
  • 处理器拿到的数据对模板进行渲染
  • 处理器向客户端返回渲染的内容作为响应

签名cookie和令牌cookie

cookie类型优点缺点
签名cookie验证cookie所需的一切信息都存储在cookie里面。cookie可以包含额外的信息, 并且对这些信息进行签名也很容易正确地处理签名很难。很容易忘记对数据进行签名,或者忘记验证数据的签名, 从而造成安全漏洞
令牌cookie添加信息非常容易。cookie的体积非常小,因此移动终端和速度较慢的客户端可以更快地发送请求需要在服务器中存储更多信息。如果使用的是关系数据库, 那么载入和存储cookie的代价可能会很高

文章投票伪代码

/**
     * 文章投票模拟
     */
@Override
public void articalVote() {
    // 散列值存储文章信息
    String articalKey = "artical:";
    redisTemplate.opsForHash().put(articalKey + "1001", "title", "文章1001");
    redisTemplate.opsForHash().put(articalKey + "1001", "votes", 528);
    redisTemplate.opsForHash().put(articalKey + "1001", "time", "20230209");
    redisTemplate.opsForHash().put(articalKey + "1002", "title", "文章1002");
    redisTemplate.opsForHash().put(articalKey + "1002", "votes", 520);
    redisTemplate.opsForHash().put(articalKey + "1002", "time", "20230209");

    // 文章发布时间有序集合
    redisTemplate.opsForZSet().add("time", "artical:1001", 20230209);
    redisTemplate.opsForZSet().add("time", "artical:1002", 20230209);
    redisTemplate.opsForZSet().add("time", "artical:1002", 20230208);
    // 文章评分有序集合
    redisTemplate.opsForZSet().add("time", "artical:1001", 528);
    redisTemplate.opsForZSet().add("time", "artical:1002", 520);
    redisTemplate.opsForZSet().add("time", "artical:1003", 100);

    // 每篇文章记录已经投票的用户
    redisTemplate.opsForSet().add("voted:1001", "user1001");
    redisTemplate.opsForSet().add("voted:1001", "user1002");
    redisTemplate.opsForSet().add("voted:1002", "user1003");
    redisTemplate.opsForSet().add("voted:1002", "user1004");
}

本章小结

在为应用程序创建新构件时,不要害怕回过头去重构已有的构件,已有的构件有时候需要进行一些细微的修改才能真正满足你的需求。

Redis 命令

字符串

在这里插入图片描述

列表

  • 列表的一个主要优点在于它可以包含多个字符串值,这使得用户可以将数据集中在同一个地方。

在这里插入图片描述

集合

在这里插入图片描述

  • 用于组合和处理多个集合的Redis命令
    在这里插入图片描述

散列

在这里插入图片描述

有序集合

在这里插入图片描述
在这里插入图片描述

发布与订阅

  • 简单理解就是将消息发送给指定频道时,频道所有的订阅者都会收到消息。订阅者可以同时收听多个频道的发出的消息
    在这里插入图片描述
  • Java 代码简单实现
@Component
public class RedisPublisher {
    public static final String CHANNEL = "channel_01";

    /**
     * Redis订阅消息监听容器
     *
     * @param connectionFactory      connection factory
     * @param messageListenerAdapter message listener adapter
     * @return RedisMessageListenerContainer
     */
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter messageListenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        // 可以添加多个MessageListener
        container.addMessageListener(messageListenerAdapter, new PatternTopic(CHANNEL));
        return container;
    }

    /**
     * 配置消息处理适配器
     *
     * @param redisConsumer redis consumer
     * @return MessageListenerAdapter
     */
    @Bean
    public MessageListenerAdapter listenerAdapter(RedisConsumer redisConsumer) {
        // messageListenerAdapter 传入一个消息接受的处理器,利用反射的方式调用对应的处理方法
        return new MessageListenerAdapter(redisConsumer, "onMessage");
    }
}

@Configuration
public class RedisConsumer implements MessageListener {

    private static final Logger logger = LoggerFactory.getLogger(RedisConsumer.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        String body = serializer.deserialize(message.getBody());
        String chanel = serializer.deserialize(message.getChannel());
        logger.info("接收的消息:{},使用的chanel:{}", body, chanel);
    }
}
  • 发布消息代码
@Override
public void publishMessage(Map<String, Object> message) {
    // 发布者
    redisTemplate.convertAndSend(CHANNEL, JSON.toJSONString(message));
}

其他命令

  • 可以根据字符串、 列表、 集合、 有序集合、 散列这5种键里面存储着的数据, 对列表、 集合以及有序集合进行排序。
    在这里插入图片描述

  • 为了对相同或者不同类型的多个键执行操作, Redis有5个命令可以让用户在不被打断的情况下对多个键执行操作, 它们分别是WATCHMULTIEXECUNWATCHDISCARD

  • Redis从一个客户端那里接收到MULTI命令时, Redis会将这个客户端之后发送的所有命令都放入到一个队列里面, 直到这个客户端发送EXEC命令为止, 然后Redis就会在不被打断的情况下, 一个接一个地执行存储在队列里面的命令

数据性能与安全保障

持久化方式

  • 配置项
#快照持久化选项
#多久执行一次自动快照操作
save 60 1000
#创建快照失败后是否仍然继续执行写命令
stop-writes-on-bgsave-error no
#是否对快照文件进行压缩
rdbcompression yes
#命名硬盘上的快照文件
dbfilename dump.rdb

#AOF持久化选项
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

#共享选项,这个选项决定了快照文件和AOF文件的保存位置。
dir ./

快照(snapshotting)

  • 如果系统发生崩溃,用户将丢失最近一次生成快照之后更改的所有数据
  • 这种方式在内存中的数据过大的时候生成快照会耗费一定的时间,即使手动生成快照也会造成耗时。
触发redis创建快照
  • 客户端向redis发送BGSAVE命令,会建立子进程将快照写入存储,同时redis可以正常接收命令。
  • 客户端向redisSAVE命令,redis在执行写入存储前不接收命令。
  • 配置文件设置快照,例如save 60 5000,可配置多个。达到条件时触发BGSAVE命令。
  • SHUTDOWN时,会触发SAVE命令。
  • slave redis发关SYNC命令后,主启动BGSAVE命令。

只追加文件(append-only file)

  • AOF持久化会将被执行的命令写到AOF文件的末尾,以此来记录数据发生的变化
appendfsync
  • appendfsync always:总是写入aof文件,并完成磁盘同步
  • appendfsync everysec:每一秒写入aof文件,并完成磁盘同步
  • appendfsync no:写入aof文件,不等待磁盘同步。

可见,从持久化角度讲,always是最安全的。从效率上讲,no是最快的。而redis默认设置进行了折中,选择了everysec,即使数据丢失也只会丢失一秒之内产生的数据

复制

  • 从服务器连接主服务器时的步骤
步骤主服务器操作从服务器操作
1(等待命令进入)连接(或者重连接)主服务,发送sync命令。
2开始执行bgsave,并使用缓冲区记录bgsave之后执行的所有写命令根据配置选项来决定是继续使用现有的数据(如果有的话)来处理客户端的命令请求,还是向发送请求的客户端返回错误。
3bgsave执行完毕,向从服务器发送快照文件,并在发送期间继续使用缓冲区记录被执行的写命令丢弃所有旧数据(如果有的话),开始载入主服务器发来的快照文件。
4快照文件发送完毕,开始向从服务器发送存储在缓冲区里面的写命令。完成对快照文件的解释操作,像往常一样开始接受命令请求。
5缓冲区存储的写命令发送完毕;从现在开始,每执行一个写命令,就向从服务器发送相应的写命令。执行主服务器发送的所有存储在缓冲区里面的写命令;并从现在开始,接受并执行主服务传来的每个写命令。
  • 从服务器在进行同步时,会清空自己的所有数据
  • Redis不支持主主复制

主从链

  • 当【读请求】的重要性明显高于【写请求】的重要性,并且读请求的数量远远超出一台Redis服务器可以处理的范围时,用户就需要添加新的从服务器来处理【读请求】。随着负载不断上升,主服务器可能会无法快速地更新所有从服务器,或者因为重新连接和重新同步从服务器而导致系统超载。为了缓解这个问题,用户可以创建一个由Redis主从节点组成的中间层来分担主服务器的复制工作。
    在这里插入图片描述

一个Redis主从复制树示例,树的中层有3个帮助开展复制工作的服务器,底层与9个从服务器。

处理系统故障

  • redis提供了对应的命令redis-check-aofredis-check-rdb验证aof文件和快照文件,是否有效。
  • 可以对aof使用–fix进行修复,但是快照目前无法修复。
  • 修复只是删除出错得命令以及位于出错命令之后得所有命令。

Redis 事务

  • 单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
  • 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

命令

  • DISCARD 取消事务,放弃执行事务块内的所有命令。
  • EXEC 执行所有事务块内的命令。
  • MULTI 标记一个事务块的开始。
  • UNWATCH 取消 WATCH 命令对所有 key 的监视。
  • WATCH key [key …] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

  • 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

命令

  • DISCARD 取消事务,放弃执行事务块内的所有命令。
  • EXEC 执行所有事务块内的命令。
  • MULTI 标记一个事务块的开始。
  • UNWATCH 取消 WATCH 命令对所有 key 的监视。
  • WATCH key [key …] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/377435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 项目必备(四十三)-->Android 开发者的 new 电脑

前言 作为 Android 开发者&#xff0c;当你新入职一家公司&#xff0c;拿到新发的电脑&#xff0c;你会对电脑干点啥&#xff1f; 安装开发环境&#xff1f;装软件&#xff1f;你是否还会铺天盖地到处找之前电脑备份的东西&#xff1f;又或者还想不起来有什么上一台电脑好用的…

一个9个月测试经验的人,居然在面试时跟我要18K,我都被他吓到了····

2月初我入职了深圳某家创业公司&#xff0c;刚入职还是很兴奋的&#xff0c;到公司一看我傻了&#xff0c;公司除了我一个测试&#xff0c;公司的开发人员就只有3个前端2个后端还有2个UI&#xff0c;在粗略了解公司的业务后才发现是一个从零开始的项目&#xff0c;目前啥都没有…

Mac iTerm2 rz sz

1、安装brew&#xff08;找了很多&#x1f517;&#xff0c;就这个博主的好用&#xff09; Mac如何安装brew&#xff1f;_行走的码农00的博客-CSDN博客_mac brew 2、安装lrzsz brew install lrzsz 检查是否安装成功 brew list 定位lrzsz的安装目录 brew list lrzsz 执…

【linux】:进程概念

文章目录 冯诺依曼体系结构一&#xff1a;操作系统二: 进程总结冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系。 冯诺依曼体系如下图&#xff1a; 那么输入设备有哪些呢&#xff1f…

时间复杂度和空间复杂度(1)

目录 1、算法效率 2、时间复杂度 1、定义 2、大O的渐进表示法 3、常见时间复杂度计算举例 3、空间复杂度 4、练习 例1、消失的数字 例2、旋转数组 1、算法效率 算法在编写成可执行程序后&#xff0c;运行时需要耗费计算机的时间资源和空间(内存)资源。因此衡量一个算法…

第八届蓝桥杯省赛——4承压计算(二维数组,嵌套循环)

题目&#xff1a;X星球的高科技实验室中整齐地堆放着某批珍贵金属原料。每块金属原料的外形、尺寸完全一致&#xff0c;但重量不同。金属材料被严格地堆放成金字塔形。7 5 8 7 8 8 9 2 7 2 8 1 4 9 1 8 1 8 8 4 1 7 9 6 1 4 5 4 5 6 5 5 6 9 5 6 5 5 4 7 9 3 5 5 1 7 5 7 9 7 4…

Unity 渲染流程管线

渲染流程图可以把它理解为一个流程&#xff0c;就是我们告诉GPU一堆数据&#xff0c;最后得出来一副二维图像&#xff0c;而这些数据就包括了”视点、三维物体、光源、照明模型、纹理”等元素。参考如下图(来自视频)CPU应用阶段剔除视锥剔除由Unity依据Camera直接完成&#xff…

PowerShell Install Tomcat

Tomcat 前言 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP 程序的首选。对于一个初学者来说&#xff0c;可以这样认为&#xff0c;当…

什么是百分比堆积条形图?

条形图实际上范围很广&#xff0c;它是以横置图形展示数据的一种图表类型。百分比堆积条形图即以堆积条形图的形式来显示多个数据序列&#xff0c;但是每个堆积元素的累积比例始终总计为 100%。它主要用于显示一段时间内的多项数据占比情况。 百分比堆叠条形图将多个数据集的条…

C++修炼之练气期一层——命名空间

目录 1.引例 2.命名空间的定义 3.命名空间的使用 4.命名空间使用注意事项 1.引例 #include <stdio.h> #include <stdlib.h>int rand 10;int main() {printf("%d\n", rand);return 0; } 当我们用C语言写下这样的代码&#xff0c;看着并没有什么语法…

Kubernetes06:Controller (Deployment无状态应用)

Kubernetes06:Controller 1、什么是controller 管理和运行容器的对象&#xff0c;是一个物理概念 在集群上管理和运行容器的对象 2、Pod和Controller之间的关系 Pod是通过controller来实现应用的运维 比如伸缩、滚动升级等等操作Pod和Controller之间通过 label 标签建立关系…

thread.join 是干什么的?原理是什么?

Thread.join 加了join&#xff0c;表示join的线程的修改对于join之外的代码是可见的。 代码示例&#xff1a; public class JoinDemo {private static int i 1000;public static void main(String[] args) {new Thread(()->{i 3000;}).start();System.out.println("…

C++学习笔记-异常处理

一个问题是程序在执行期间产生了一个例外。 C异常是一个特殊的情况在程序运行时&#xff0c;比如试图除以零而引致的响应结果。 异常提供一种方法来从一个程序到另一个程序的一个部分转移控制。 C异常处理建立在三个关键字&#xff1a; try, catch,和 throw。 throw: 程序抛出…

72. import 导入标准模块(os模块)

72. import 导入标准模块(os模块) 文章目录72. import 导入标准模块(os模块)1. 标准模块知识回顾2. os 模块的基本介绍3. import 导入标准模块1. 方法12. 方法21. 导包不同2. 声明不同3. 路径不同4. 概括3. 方法34. 方法44. 调用模块或库中的类、函数、变量5. os模块的路径操作…

Git ---- 国内代码托管中心-码云

Git ---- 国内代码托管中心-码云1. 简介2. 码云账号注册和登录3. 码云创建远程仓库4. IDEA 集成码云1. IDEA 安装码云插件2. IDEA 连接码云5. 码云复制 GitHub 项目1. 简介 众所周知&#xff0c;GitHub 服务器在国外&#xff0c;使用 GitHub 作为项目托管网站&#xff0c;如果…

InnoDB数据页结构__盛放记录的大盒子

一、不同类型的页简介 前边我们简单提了一下页的概念&#xff0c;它是InnoDB管理存储空间的基本单位&#xff0c;一个页的大小一般是16KB。InnoDB为了不同的目的而设计了许多种不同类型的页&#xff0c;比如存放空间头部信息的页&#xff0c;存放Insert Buffer信息的页&#xf…

「TCG 规范解读」TCG 软件栈 TSS (上)

可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alliance,TCPA)所开发的规范。现在的规范都不是最终稿,都…

谈谈XR关键技术及VR/AR/MR/XR关系

一、先别被VR/AR/MR/XR搞晕&#xff0c;说说区别虚拟现实&#xff08;Virtual Reality&#xff0c;VR&#xff09;、增强现实&#xff08;Augmented Reality&#xff0c;AR&#xff09;等业务以其三维化、自然交互、空间计算等完全不同于当前移动互联网的特性&#xff0c;被认为…

Kylin V10桌面版arm3568 源码安装redis

上传redis-5.0.14.tar.gz到/home/kylin/下载&#xff1b;解压kylinkylin:~/下载$ tar -zxvf redis-5.0.14.tar.gz/opt下新建redis目录&#xff0c;并将上面解压的文件夹移到此处kylinkylin:~/下载$ sudo mv redis-5.0.14 /opt/redis/编译&#xff1a;kylinkylin:/opt/redis/red…

ACP、PMP、NPDP含金量哪个高?

在自个的领域而言&#xff0c;知名度、报考人数相对较高&#xff0c;这里我就说下他们的含金量吧。&#xff08;含资料&#xff09; 【ACP】 项目管理相关的证书 1、增加项目管理能力&#xff0c;并且对你拥有的知识与技能起到了很好的证明。不断提高自己的能力&#xff0c;不…