Redis这一篇就够了

一.概述

Redis是什么?
Redis是远程服务字典服务,是一个开源的使用ANSI C语言编写,支持网络,可基于内存亦可持久化的日志型,Key-Value数据库,并提供多种语言的API。
redis会周期性把更新的数据写入磁盘或把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。免费开源,是NoSQL技术之一,也称为结构化数据库。
Redis能干嘛?

  1. 内存存储,持久化,内存中是断电即失,所以说持久化很重要
  2. 效率高,可用于高速缓存
  3. 发布订阅系统
  4. 地图信息分析
  5. 计时器,计数器

二.Redis的基本了解

官方文档:
英文官方文档:https://redis.io/
中文文档:http://www.redis.cn/
Redis-Key常用命令:
http://www.redis.cn/commands.html

127.0.0.1:6379> ping  #查看当前连接是否正常,正常返回PONG
PONG
127.0.0.1:6379> clear  #清楚当前控制台(为了更好的看到下面输入的命令)
127.0.0.1:6379> keys *  #查看当前库里所有的key
1) "db"
127.0.0.1:6379> FLUSHALL  #清空所有库的内容
OK
127.0.0.1:6379> set name dingdada  #添加一个key为‘name’ value为‘dingdada’的数据
OK
127.0.0.1:6379> get name  #查询key为‘name’的value值
"dingdada"
127.0.0.1:6379> EXISTS name  #判断当前key是否存在
127.0.0.1:6379> move name 1  #移除当前库1的key为‘name‘的数据

三.五大数据类型

1. Redis通用命令

在这里插入图片描述

2. Redis数据类型

2.1 String - 字符串类型

在这里插入图片描述

字符串命令:
在这里插入图片描述

String表面上是字符串,但其实他可以灵活的表示字符串,整数,浮点数3种值。Redis自动识别这3种值

127.0.0.1:6379> set key1 "hello world!"  #注意点:插入的数据中如果有空格的数据,请用“”双引号,否则会报错!
OK
127.0.0.1:6379> set key1 hello world!  #报错,因为在Redis中空格就是分隔符,相当于该参数已结束
(error) ERR syntax error
127.0.0.1:6379> set key1 hello,world!  #逗号是可以的
OK
127.0.0.1:6379> incr num  #指定key为‘num’的数据自增1,返回结果  相当于java中 i++
(integer) 1
127.0.0.1:6379> get num  #一般用来做文章浏览量、点赞数、收藏数等功能
"1"
127.0.0.1:6379> decr num  #可以一直减为负数~
(integer) -1
127.0.0.1:6379> decr num  #一般用来做文章取消点赞、取消收藏等功能
#截取
127.0.0.1:6379> GETRANGE key1 0 4  #截取字符串,相当于java中的subString,下标从0开始,不会改变原有数据
"hello"
127.0.0.1:6379> get key1
"hello world!"
127.0.0.1:6379> GETRANGE key1 0 -1  #0至-1相当于 get key1,效果一致,获取整条数据
#替换
"hello world!"
127.0.0.1:6379> SETRANGE key2 5 888  #此语句跟java中replace有点类似,下标也是从0开始,但是有区别:java中是指定替换字符,Redis中是从指定位置开始替换,替换的数据根据你所需替换的长度一致,返回值是替换后的长度
(integer) 14
127.0.0.1:6379> get key2
"hello888world!"
127.0.0.1:6379> SETRANGE key2 5 67  #该处只替换了两位
(integer) 14
127.0.0.1:6379> get key2
"hello678world!"
#设置过期时间,跟Expire的区别是前者设置已存在的key的过期时间,而setex是在创建的时候设置过期时间
127.0.0.1:6379> setex name1 15  dingdada  #新建一个key为‘name1’,值为‘dingdada’,过期时间为15秒的字符串数据
OK
127.0.0.1:6379> ttl name1  #查看key为‘name1’的key的过期时间
(integer) 6
#不存在设置
127.0.0.1:6379> setnx name2 dingdada2  #如果key为‘name2’不存在,新增数据,返回值1证明成功
(integer) 1
127.0.0.1:6379> get name2
"dingdada2"
127.0.0.1:6379> keys *
1) "name2"
127.0.0.1:6379> setnx name2 "dingdada3"  #如果key为‘name2’的已存在,设置失败,返回值0,也就是说这个跟set的区别是:set会替换原有的值,而setnx不会,存在即不设置,确保了数据误操作~
(integer) 0
127.0.0.1:6379> get name2
"dingdada2"

2.2 Hash - Hash键值类型

Hash类型用于存储结构化数据
在这里插入图片描述

键-键-值
Hash 命令:
在这里插入图片描述

2.3 List - 列表类型
List列表就是一系列字符串的“数组”,按插入顺序排序
List列表最大长度为2的32次方-1,可以包含40亿个元素
List 命令
在这里插入图片描述

小结:
实际上是一个链表,before Node after , left,right 都可以插入值
如果key 不存在,创建新的链表
如果key存在,新增内容
如果移除了所有值,空链表,也代表不存在!
在两边插入或者改动值,效率最高! 中间元素,相对来说效率会低一点
消息排队!消息队列 (Lpush Rpop), 栈( Lpush Lpop)!

2.4 Set - 集合类型

Set集合是字符串的无序集合,集合成员是唯一的
在这里插入图片描述

2.5 Zset - 有序集合类型

Zset集合是字符串的有序集合,集合成员是唯一的
它的实质是每个数据对应了分数
在这里插入图片描述

总结:成绩表排序,工资表排序,年龄排序需求可以用zset来实现

四.三大特殊数据类型的学习和理解

1.Geospati:地理位置

城市维度查询:https://jingweidu.bmcx.com/
注意:
两极无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入
有效的经度从-180度到180度。
有效的纬度从-85.05112878度到85.05112878度。
m 为米。km 为千米。mi 为英里。ft 为英尺。
在这里插入图片描述

实际需求中,我们可以用来查询附近的人,计算两人之间的距离等。当然,那些所需的维度我们肯定要结合java代码来一次导入,手动查询和录入太过浪费时间。

2.Hyperloglog:基数

什么是基数?
数学层面上指两个数集中不重复的元素
但在redis中,可能会有一定误差,官方给的误差率为0.81%
Hyperloglog优点:占用的内存是固定的,2^64个元素,相等于只需要12kb的内存即可。效率高。
在这里插入图片描述

实际需求中,运行一定的误差值,我们可以使用技术统计来计算,效率非常高,如网站访问量,就可以利用Hyperloglog来进行计算统计

3.Bitmap:位存储

Bitmap位图,数据结构,都是操作二进制位来进行记录,只有0和1状态
在这里插入图片描述

实际需求中,可能需要我们统计用户的登录信息,员工的打开信息等。只要是事物的只有两种状态,我们都可以使用Bitmap来进行操作。

五.Redis中的事物和乐观锁如何实现?

1. 前言

事务的ACID:MySQL事务
在Redis中没有隔离级别的概念
在Redis单条命令式保证原子性,但是事物不保证原子性
乐观锁:
①当程序中可能出现并发的情况时,就需要保证在并发情况下数据的准确性,以此确保当前用户和其他用户一起操作时,所得到的结果和他单独操作时的结果是一样的。
②没有做好并发控制,就可能导致脏读、幻读和不可重复读等问题。
在Redis是可以实现乐观锁的!

2. Redis如何实现事务?

正常执行事务

127.0.0.1:6379> multi  #开启事务
OK
127.0.0.1:6379> set name dingyongjun  #添加数据
QUEUED
127.0.0.1:6379> set age 26  #添加数据
QUEUED
127.0.0.1:6379> set high 172  #添加数据
QUEUED
127.0.0.1:6379> exec  执行事务
1) OK
2) OK
3) OK
127.0.0.1:6379> get name  #获取数据成功,证明事务执行成功
"dingyongjun"
127.0.0.1:6379> get age
"26"

放弃事务

127.0.0.1:6379> multi  #开启事务
OK
127.0.0.1:6379> set name dingyongjun  #添加数据
QUEUED
127.0.0.1:6379> set age 26  #添加数据
QUEUED
127.0.0.1:6379> discard  #放弃事务
OK
127.0.0.1:6379> get name  #不会执行事务里面的添加操作
(nil)

③编译时异常,代码有问题,或者命令有问题,所有的命令都不会被执行

127.0.0.1:6379> multi  #开启事务
OK
127.0.0.1:6379> set name dingyongjun  #添加数据
QUEUED
127.0.0.1:6379> set age 23  #添加数据
QUEUED
127.0.0.1:6379> getset name  #输入一个错误的命令,这时候已经报错了,但是这个还是进入了事务的队列当中
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set high 173  #添加数据
QUEUED
127.0.0.1:6379> exec  #执行事务,报错,并且所有的命令都不会执行
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get name  #获取数据为空,证明没有执行
(nil)

运行时异常,除了语法错误不会被执行且抛出异常后,其他的正确命令可以正常执行

127.0.0.1:6379> multi  #开启事务
OK
127.0.0.1:6379> set name dingyongjun  #添加字符串数据
QUEUED
127.0.0.1:6379> incr name  #对字符串数据进行自增操作
QUEUED
127.0.0.1:6379> set age 23  #添加数据
QUEUED
127.0.0.1:6379> get age  #获取数据
QUEUED 
127.0.0.1:6379> exec  #执行事务。虽然对字符串数据进行自增操作报错了,但是其他的命令还是可以正常执行的
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "23"
127.0.0.1:6379> get age  #获取数据成功
"23"

总结:由以上可以得出结论,redis是支持单条命令事务的,但是事务并不能保证原子性

3. Redis如何实现乐观锁

watch(‘监听’)

127.0.0.1:6379> set money 100  #添加金钱100
OK
127.0.0.1:6379> set cost 0  #添加花费0
OK
127.0.0.1:6379> watch money  #监控金钱
OK
127.0.0.1:6379> multi  #开启事务
OK
127.0.0.1:6379> DECRBY money 30  #金钱-30
QUEUED
127.0.0.1:6379> incrby cost 30  #花费+30
QUEUED
127.0.0.1:6379> exec  #执行事务,成功!这时候数据没有发生变动才可以成功
1) (integer) 70
2) (integer) 30

多线程测试watch
线程一

#线程1
127.0.0.1:6379> set money 100  #添加金钱100
OK
127.0.0.1:6379> set cost 0  #添加花费0
OK
127.0.0.1:6379> watch money  #开启监视(乐观锁)
OK 
127.0.0.1:6379> multi  #开启事务
OK
127.0.0.1:6379> DECRBY money 20  #金钱-20
QUEUED
127.0.0.1:6379> INCRBY cost 20   #花费+20
QUEUED
#这里先不要执行,先执行线程2来修改被监视的值
127.0.0.1:6379> exec  #执行报错,因为我们监视了money这个值,如果事务要对这个值进行操作前
#监视器会判断这个值是否正常,如果发生改变,事务执行失败!
(nil)

线程二:

#线程2,这个在事务执行前操作执行
127.0.0.1:6379> INCRBY money 20  #金钱+20
(integer) 120

总结:
悲观锁: 什么时候都会出问题,所以一直监视着,没有执行当前步骤完成前,不让任何线程执行,十分浪费性能!一般不使用!
乐观锁: 只有更新数据的时候去判断一下,在此期间是否有人修改过被监视的这个数据,没有的话正常执行事务,反之执行失败!

六.Redis线程相关知识

Redis 是单线程的,这意味着它在任何给定时刻只会执行一个操作。虽然 Redis 是单线程的,但它通过使用非阻塞 I/O 和基于事件驱动的设计来实现高性能和并发处理。
Redis 的单线程架构使其非常快速,因为它无需处理线程之间的竞争条件和锁定。相反,Redis 依靠高效的内存数据存储和快速的非阻塞 I/O 操作来提供高吞吐量和低延迟。此外,Redis 还使用了一些技术来确保数据的一致性和持久性,如写日志和定期的数据快照。
虽然 Redis 主进程是单线程的,但它可以在后台启动多个附加线程来执行不同的任务,如数据持久化和复制。这些附加线程不会影响主线程的性能,因为它们通常处于低优先级状态,并且它们的工作不会阻塞主线程的执行。这使得 Redis 能够在单个线程下实现高性能和并发处理,成为一个非常受欢迎的内存数据库和缓存服务器。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

米尔MYC-Y6ULX-V2开发板测评记录

文章目录 1、板子上手体验2、板载硬件3、系统信息4、 驱动测试5、编译linux三大件7、摄像头测试9、总结 1、板子上手体验 首先非常感谢芯查查给了这样一个机会来测评这样一款性能十分强大的开发板,我拿到手的是MYC-Y6ULX-V2核心板及开发板,这块板子具有…

SSMP整合案例第六步 在前端页面上利用axios和element-ui与后端交互实现增删改

新增操作 正常我们都是从新增功能书写 查看源码 显示的是这个 在vue里面开下来 这样就能显示 点击确定 就能把数据发送到后台进行保存 //弹出添加窗口handleCreate() {this.dialogFormVisible true;},//重置表单resetForm() {},//添加handleAdd() {//绑定的是确定按钮 发起请…

IDM优势

目录 🐋引言 🐋IDM的核心优势 🦈下载速度提升 🐟技术原理: 🐟对比示例: 🦈断点续传 🐟技术原理: 🐟对比示例: 🦈集…

牛客热题:缺失的第一个正整数

牛客热题:数组中出现一次的两个数字> 📟作者主页:慢热的陕西人 🌴专栏链接:力扣刷题日记 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 文章目录 …

如何使用golang自带工具对代码进行覆盖率测试

在 Go 语言中,测试代码覆盖率通常使用 go test 命令结合 -cover 和 -coverprofile 1. 基本代码覆盖率报告 在项目目录下运行以下命令 go test -cover这将在控制台输出一个代码覆盖率的百分比。但是,这种方式不会保存覆盖率数据(可以指定目…

961操作系统知识总结

部分图片可能无法显示,参考这里:https://zhuanlan.zhihu.com/p/701247894 961操作系统知识总结 一 操作系统概述 1. 操作系统的基本概念 重要操作系统类型:批处理操作系统(批量处理作业,单道批处理/多道批处理系统,用…

将 py 文件编译成 pyd 文件

文章目录 一、简介1.1、Python中的文件类型:.py .pyc .pyd1.2、基本原理1.2.1、函数详解:Extension() —— 用于定义扩展模块(C/C 扩展)的类1.2.2、函数详解:setup() —— 用于配置和构建包的函数 二、构建过程2.0、…

带交互的卡尔曼滤滤波|一维滤波|源代码

背景 一维卡尔曼滤波的MATLAB例程,​背景为温度估计。 代码介绍 运行程序后,可以自己输入温度真实值: 以20℃为例,得到如下的估计值​: 滤波前的值和滤波后的值分别于期望值(真实值)作差…

海光CPU:国产信创的“芯“动力解读

国产信创CPU-海光CPU CPU:信创根基,国之重器 国产CPU形成三大阵营:自主架构、x86及ARM。自主阵营中,龙芯和申威以LoongArch和SW-64为基石;ARM阵营由鲲鹏、飞腾主导,依托ARM授权研发处理器;x86阵…

Python知识点17---包

提前说一点:如果你是专注于Python开发,那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了,而如果你和作者一样只是操作其他技术的Python API那就足够了。 Python的包,你可以把它看成是一个大的模块,它…

【Java】javafx界面布局

目录 一、面板类 (1)Pane面板 (2)HBox面板 (3)VBox面板 (4)BorderPane面板 (5)FlowPane面板 (6)GridPane面板 (7)StackPane面…

生命在于学习——Python人工智能原理(3.1)

三、深度学习 (一)深度学习的概念 1、深度学习的来源 深度学习的概念来源于人工神经网络,所以又称深度神经网络。 人工神经网络主要使用计算机的计算单元和存储单元模拟人类大脑神经系统中大量的神经细胞(神经元)通关…

【精读文献】J. Environ. Manage.|青藏高原生态恢复项目下植被覆盖动态及其对生态系统服务的约束效应

目录 文章简介 01 文章摘要 02 研究背景、目标及创新点 2.1 研究背景 2.2 研究现状 03 研究区域与数据集 3.1 研究区域 3.2 研究数据 04 研究方法 4.1 趋势分析 4.2 残差趋势分析 4.3 偏相关 4.4 生态系统服务评价 4.5 约束线的定义和提取 05 研究结果 5.1 植被…

重学java 55. 集合 Set接口

我救自己万万次,铮铮劲草,绝不动摇 —— 24.6.2 一、Set集合介绍 Set和Map密切相关的 Map的遍历需要先变成单列集合,只能变成set集合 二、HashSet集合的介绍和使用 1.概述 HashSet是Set接口的实现类 2.特点 a、元素唯一 b、元素无序 c、无索引…

单元测试的心法分享

大家好,我是G探险者! 今天我们简单聊聊单元测试的哪些事儿~ 两天时间我玩明白了单元测试的套路。 这里我分享一下思路。 在我眼里单元测试室什么? 请看这张草图: 单元测试主要关注单个代码单元(通常是类或方法&am…

云原生架构案例分析_2.云原生技术助力某汽车公司数字化转型实践

名词解释: 互联网 在“互联网”模式下,我们仅仅把互联网看作是一种传播工具、传播手段、传播渠道和传播平台,对于互联网的应用大体上是在既有的运作逻辑的基础之上,把互联网作为延伸传媒影响力、价值和功能的一种延伸型工具&…

秒杀基本功能开发(不考虑高并发情况)

文章目录 1.显示秒杀状态1.controller修改GoodsController.java的toDetail方法,响应秒杀状态和秒杀剩余时间 2.前端1.goodsDetail.html 图片下面添加一行秒杀开始时间2.goodsDetail.html 添加计时器js代码 3.测试1.秒杀进行中2.修改db的秒杀开始时间为明天3.出现秒杀…

msvcr120.dll是干嘛的?出现找不到msvcr120.dll丢失怎样解决

msvcr120.dll是Microsoft Visual C 2012 Redistributable的核心文件,它是Microsoft Corporation开发的C/C运行时库文件之一。这个文件通常与应用程序一起安装,为应用程序提供许多基本的运行时功能,包括内存管理、异常处理、输入/输出操作等。…

Jenkins、GitLab部署项目

1、安装JDK 1.1、下载openJdk11 yum -y install fontconfig java-11-openjdk1.2、查看安装的版本号 java -version1.3、配置环境变量 vim /etc/profile在最底部添加即可 export JAVA_HOME/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64 export PATH$JAVA_HOME/…

SpringBoot注解--10--@Bean,对象注入的三种方法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Bean一、如何使用方法注解注意Bean 的命名规则,当没有设置 name 属性时,那么 bean 默认的名称就是方法名,当设置了 name 属性之后…