Redis 入门到分布式 (二)API的理解和使用
个人博客网:https://wushaopei.github.io/ (你想要这里多有)
内容:
- 通用命令
- 单线程架构
- 数据结构和内部编码
一、常用的通用命令:
- keys 计算所有的键
- dbsize 获取redis的长度
- exists key 判断键的存在与否
- del key [key ...] 删除指定键的值
- expire key seconds 对key做定时操作
- type key
1、keys
1)用法1:
2)用法2:
说明: keys命令一般不在生产环境使用
2、dbsize:
3、exists:
4、del:
5、expire、ttl、persist
演示:
6、type:
7、命令的时间复杂度:
二、数据结构和内部编码
1、Redis的主要数据结构:
Redis的内部隐含结构体(对象): redis Object
2、该结构体包含以下数据类型及编码方式:
三、单线程
1、抽象理解Redis的单线程:
我们知道一个命令进入Redis执行的效率是很高的,在进入Redis之前可以认为它们在经过一条高速公路,如图中的黄色管道部分,而这条管道每一次都只能通过一个命令,多余的命令需要等待前面的命令执行完成后才能进入Redis中执行相应操作,也就是说,多个命令在操作Redis时是串行执行的。
2、单线程为什么这么快?
1)纯内存:
内存的响应速度是非常快的,内存的响应速度是100纳秒;也就是说Redis的速度高是依赖于内存的;
2)非阻塞IO
Redis中将equals和关闭、读写、连接转换为自己的一个事件,从而避免在网络IO上浪费过多的时间。
3)避免线程切换和竞态消耗
单线程equals模型
一瞬间只能执行一条命令
3、单线程:
1)一次只运行一条命令
2)拒绝长(慢)命令
Keys , flushall , flushdb , slow lua script , mutil / exec , operate big value ( collection )
3)其实不是单线程
fysnc file descriptor
close file descriptor
四、字符串
字符串:
- 结构和命令
- 快速实战
- 内部编码
- 查漏补缺
1、字符串键值结构
对于Redis来说,所有的key都是字符串,而它的value则是前面说过的五种类型。这里主要对Redis的value进行解析。当前的value为字符串类型
如上图,value是“world”,是一个字符串的类型
同样的,字符串的value也可以是一个数值类来表示
并且,字符串也可以做相应的转换,在字符串和整型间做转换,其原理类似于位图的使用。
① 字符串的value的表现形式也可以是以json的形式存在
② 字符串的value 最大限制为512MB的容量。
2、字符串的value的适用场景:
- 缓存;
- 计数器:例如:视频网站的视频的播放次数,每一次的播放会做加一的操作;
- 分布式锁;
- 等等。。。
3、字符串value的相关API操作:get、set、del、
其他的API的使用:Incr、decr、incrby、decrby:
4、演示:
5、实战
1)实战1:
实现如下功能:记录网站每个用户个人主页的访问量?
Incr userid : pageview (单线程:无竞争)
当用户的userid为123时, 以 incr 123:pageview的形式来进行自增,由于单线程执行,每个key都是一次执行的,不存在并发的问题,每次有新的访问就会提交一次 incr 123:pageview 的请求,依次累加达到访问量的计数。
2)实战2:
实现如下功能:缓存视频的基本信息(数据源在MySQL中)伪代码
如图,用户通过视频的id去获取视频的信息,首先会从App Server发起请求,App Server 会先从redis查询是否有匹配视频id的视频信息,如果redis中存在了,就直接返回给App Server,这就减少了数据库MySQL的压力;如果不存在,就会直接访问MySQL,从MySQL查询到了视频信息,就会回写到redis中,并同时返回给App Server。
下一次,用户访问接口或App Server时,依旧会从redis中访问,这无论是对应用的性能还是mysql减少压力都会有很大的优势。
伪代码实现:
首先,使用视频id和redisPrefix定义一个redis的key,然后从redis中获取key对应的 VideoInfo,再判断vaideoInfo如果为空,则从mysql中查询并返回对应视频id的视频信息 videoInfo;再次判断videoInfo 从mysql返回的结果不为空后进行序列化并set存入到redis 中。
3)实战3:
实现如下功能:分布式id生成器
比如我们有三个java的服务,我们希望每次获取到的id是自增的,并且是由三个服务去并发的获取,必须满足不重复又逐步递增。
解决方法:
incr id (原子操作)
使用 incr 对共享的id进行操作,该操作由于原子性,可保证并发安全。
6、key 的设置命令:set setnx setxx
演示:
7、批量操作API:mget mset
演示:
8、延伸:
1)n次get
n次get = n次网络时间 + n次命令时间
由于大部分情况下,应用的客户端和服务端都处在不同的地区或机房,双方的信息交换即网络时间是一个很大的开销,而由于redis本身的优越性能,命令本身的开销是非常小的。
2)1次mget
1次mget = 1次网络时间 + n次命令时间
使用批量操作可以大大减少网络时间的消耗,有利于提高性能和效率。
9、Redis 的API : getset 、append、strlen
演示:
10、Redis 的API :incrbyfloat 、getrange、setrange
演示:
11、字符串总结:
五、 hash(1)
哈希:
- 特点
- 重要API
- hash vs string
- 查漏补缺
1、哈希键值结构:
如图:哈希的结构也是主要由键值结构组成,即key - value;但是其value是由 field 和 value 组成。
由于field属性的存在,与value构成了类似双列集合的结构,我们可以根据需要在相同的key ,即user:1:info 中添加一个field为viewCounter、value为50的值。
2、具体操作如下:
add a new value
3、特点:
Mapmap:它的结构类似于一个包含了map的map;
Small redis: 由以上的mapmap结构可知,它就像包含了一个小的redis结构的redis
field不能相同,value可以相同:field类似于key ,每一个都是唯一的
4、相关API:hget 、hset、hdel
演示:
5、相关API: hexists 、hlen
演示:
6、API: hmget、hmset
演示:
六、hash(2)
1、实战:
1)实现如下功能:记录网站每个用户个人主页的访问量?
具体实现:
hincrby user:1:info pageview count
分析:
用user:1:info作为用户id,在用户的信息里面添加一个叫pageview的属性作为访问量的字段,这样可以让访问量的属性与用户信息成为一个整体,当有一个用户访问时,count为1,则访问量加1。
演示:
redis> HSET myhash field 5
(integer) 1
redis> HINCRBY myhash field 1
(integer) 6
redis> HINCRBY myhash field -1
(integer) 5
redis> HINCRBY myhash field -10
(integer) -5
2) 实现如下功能: 缓存视频的基本信息(数据源在mysql中)伪代码:
2、API:hgetall key、hvals key、hkeys key
演示:
小心使用hgetall,有redis是单线程的,使用hgetall取出多个信息的时候会有效率上的问题,即数据量过大时,如1万个value时,获取结果会很慢。
3、相似的API:
4、如何更新用户的属性:
1)使用字符串1:
将用户id作为key,并将用户属性及值的集合转换为json作为value保存到redis中;做更新操作时,根据用户id去取得所有的属性及值的json集合,由json格式转换为用户对象类型;对要修改的部分做增删改操作,将修改后的对象数据进行序列化,重新保存到对应用户id的redis中,覆盖原来的value值。
2)使用字符串2:
如图中,将用户的信息根据用户id+属性名的方式进行拼接作为key,这样该用户的所有信息都是单独保存到redis中,在进行修改时只需要根据对应的key就可以进行修改了,将修改后的数据重新覆盖原来的信息。
同时的,在进行添加新的属性时,只需要按照key的规则进行单独添加即可。
3)使用hash:
用户信息(hash)
如图中,将用户的属性作为value的field,属性值作为vlue来进行添加到用户id作为key的redis中。更新用户信息时直接使用hset user:1:infor age 41 进行操作便可实现age的修改,同样也可以用来进行新增操作:如图中的link属性。
5、3种方案比较:
6、查漏补缺:
7、哈希总结:
七、 list(1)
列表:
- 特点
- 重要API
- 实战
- 查漏补缺
1、列表结构:
可以对列表做一些操作:如左边的添加、右边的添加、左边的弹出、右边的弹出
也可以获取列表的长度、删除指定元素、获取字列表、获取指定元素的索引值
2、特点:
- 有序
- 可以重复
- 左右两边插入弹出
3、增——rpush
例如:使用rpush 向右边插入值 c b a
4、增——Ipush
例如:使用Ipush从右向左依次插入c b a
八、list(2)
1、增——linsert
例如:向值b的左边或右边插入值java或php
2、删——Ipop:
例如:从列表左侧弹出一个key ,弹出对象不需要指定,只需指定该列表listkey即可
3、删—— rpop:
例如:从列表右侧弹出一个key ,弹出对象不需要指定,只需指定该列表listkey即可
4、删——Irem :
例子:删除所有的a,从右到左删除1个c
5、列表修剪—— Itrim:
例如:第一次修剪索引1-4的值为:b(0)、c(1)、d(2)、e(3)
第二次修剪索引0-2的值为: b(0)、c(1)、d(2)、
Itrim在做一些大型列表的删除时是非常有用的,比如:一个列表有几百万,如果直接使用delkey的话会直接将redis阻塞掉,因为它的开销是非常大的。
而通过使用Itrim就可以通过每一个保留百万条、十万条、万条等等这样的方式去逐步的进行裁剪,从而达到删除的效果。
6、查——Irange:
例如:根据索引从左向右(0~5)或从右向左(-1~6)的查询
例如:保存0~2索引区间:a、bc、
保存1~-1索引区间:b、c、d、e、f
7、查—— lindex :
例如:获取索引为0的是a ;获取索引为-1的是f
8、查—— llen
例如:当前的长度是6
9、改 —— lset
例如:将索引为2的值改为java,即java覆盖值c
演示:
10、实战—— TimeLine
图中展示了微博的时间轴功能—— TimeLine,它会将微博按照从新到旧的功能进行排列,这和列表的功能是非常相似的。
假设图中的Your TimeLine是你微博的时间轴,如果你关注的用户有了更新,俺么该更新信息就会加入到时间轴的左上角,进入队列中。
在微博之中,包含了文字、图片、赞等等信息,可作为对象看待,存储的时候可以使用字符串或hash等等,而微博的id可以作为一个外联的key,这样就可以对微博的获取进行关联。
11、查漏补缺: -- blpop brpop:
12、总结:
①如果要实现一个栈的功能:
LRUSH + LPOP = Stack
②如果要实现一个堆的功能:
LRUSH +LPOP = Stack
③如果要控制一个有固定数量的列表,而不是让它无限制放大:
LPUSH + LTRIM = Capped Collection
④如果要实现一个消息队列的系统:
LPUSH + BRPOP = Message Queue
九、set
set:
- 集合结构
- 特点
- 集合内API和实战
- 集合间API和实战
1、特点:
- 无序
- 无重复
- 支持集合间操作
2、增—— sadd srem :
工具—— scard 、sismember、srandmember、smembers、
注意: smembers 是无序且单线程的。
srandmember 和 spop:
- spop 从集合弹出元素
- srandmember不会破坏集合
演示:
3、实战
1)实战——抽奖系统:
以微博的抽奖为例,只要用户的量不是太大,可以把用户信息放入到集合中去,可以使用can be spop 进行弹出操作,在取出之后进行删除。
2)实战——标签(tag)
4、sdiff(差集) 、sinter(交集)、sunion(并集)
5、集合的使用场景:
1) SADD = Tagging 做标签
2) SPOP/SRANDMEMBER = Random item 随机数
3) SADD + SINTER = Social Graph 社交相关的场景
十、 zset
有序集合:
- 特点
- 重要API
- 实战
- 查漏补缺
1、有序结合的结构:
上图是有序集合的结构图,有序集合同样是有key-value键值结构的,但是它的value是由score和value构成的。它的有序是由score分值支持的,这与排序无关,所谓有序是指它的score是唯一的,并且由数值构成,意味着score的值是有序的。
2、集合和有序集合的对比:
3、列表和有序集合的对比:
4、增—— zadd :
例如:为id 为 user:1:ranking的用户添加一个score为225的element为tom的value
5、删—— zrem :
例如:删除id为user:1:ranking 的用户的score为225且element为tom的value
6、查—— zscore:
例如:获取有序集合中元素为tom的分数score 225.
7、自增或自减 —— zincrby:
例如:将元素为mike的分数增加9,达到100.
8、查个数——zcard :
例如:返回key为user:1:ranking 的元素的总个数
演示:
9、按照索引排名—— zrange :
例如:获取有序集合中索引为1到3的元素 mike 、frank、charis
10、按照分数排名——zrangebyscore :
例如:获取90分到123分的元素: mike 、frank
11、获取指定分数范围的元素个数—— zcount :
例如:获取200到210之间的个数: 2
12、按照排名范围进行元素的删除—— zremrangebyrank :
例如:删除集合中索引为1和2的元素
13、按照分值范围进行元素的删除 —— zremrangebyscore :
例如:将90到210间分数的元素删除
演示:
14、实战——排行榜 :
使用有序集合对新书榜单进行分数、销量、评价等进行排序。
15、有序集合总结:
Redis 入门到分布式 (二)API的理解和使用的更多相关文章
- Redis入门教程(二)
推荐阅读: Redis入门教程(一)https://www.cnblogs.com/jichi/p/10285346.html 5. Redis 的数据结构 5.1 Redis 数据结构介绍 redi ...
- Redis入门指南之二(安装及配置)
本节主要内容 1. 前言2. redis安装3. 启动和停止Redis 1. 前言 安装Redis需要知道自己需要哪个版本,有针对性的安装,比如如果需要redis GEO这个地理集合的特性,那么red ...
- Redis 入门到分布式 (一)Redis初识
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.Redis特性目录 Redis的特性: 速度快 持久化 多种数据结构 支持多种编辑语言 功能丰富 简 ...
- redis入门指南(二)—— 数据操作相关命令
写在前面 以下绝大部分内容取材于<redis入门指南>,部分结合个人知识,实践后得出. 只记录重要,明确,属于新知的相关内容,杜绝冗余和重复. 字符串 1.字符串类型是redis中最常见的 ...
- Redis 入门到分布式 (四) 瑞士军刀Redis其他功能
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 目录: 慢查询 Pipeline 发布订阅 Bitmap(位图) HyperLogLog GEO 一.慢 ...
- Redis入门教程(二)— 基本数据类型
阅读以下内容时,手边打开一个redis-cli一起输入,输入命令敲击回车键前在心中想好你的答案,如果结果不合你的预期,请分析原因,使极大地提高学习效率.如果没有条件,每个数据类型后有代码运行结果,供你 ...
- Redis 入门到分布式 (五) Redis持久化的取舍和选择
个人博客网:https://wushaopei.github.io/ (你想要这里多有) Redis持久化的取舍和选择 持久化的作用 RDB AOF RDB和AOF的选择 一.持久化的作用 ...
- webpack入门和实战(二):全面理解和运用loader和plugins
您的阅读目录: 一.理解webpack加载器loader 二.理解less-loader加载器的使用 三.理解babel-loader加载器的使用 四.webpack命令行常见使用的操作 五.用web ...
- <Redis> 入门X 分布式锁
分布式其实就是多进程的程序,当多个进程访问一个资源,会造成问题: 1.资源共享的竞争问题 2.数据的安全性 分布式锁的解决方案: 1.怎么去获取锁 数据库 zookeeper redis 2.怎么释放 ...
随机推荐
- OpenCV Error: Unspecified Error(The Function is not implemented)
Ubuntu 或者 Debian 系统显示窗口的时候遇到了这个问题 error: (-2:Unspecified error) The function is not implemented. Reb ...
- JDBC14 ORM03 JavaBean封装
Javabean对象封装一条信息(推荐) 让JavaBean的属性名和类型尽量和数据库保持一致 一条记录对应一个对象,将这些查询到的对象放到容器中(List) 表信息如下 List封装多条信息 Con ...
- [hdu4801]搜索
http://acm.hdu.edu.cn/showproblem.php?pid=4801 状态和生成状态的过程处理好了,这个题就是简单的搜索题了== #include <iostream&g ...
- MySQL 查询当天、本周,本月、上一个月的数据
mysql查询当天的所有信息: SELECT * FROM 表名 WHERE year(时间字段名)=year(now()) and month(时间字段名) = month(now()) and d ...
- dedecms_v5.7的apache文件名解析漏洞的学习
0x00 Apache文件名解析漏洞 Apache是一个Web服务器,可以提供web服务.配合java中间件.PHP实现动态页面访问. Apache和PHP通过接口接入后,Apache接受用户的请求, ...
- 1、Fiddler基础
1.抓取https请求 前言 fiddler是一个很好的抓包工具,默认是抓http请求的,对于pc上的https请求,会提示网页不安全,这时候需要在浏览器上安装证书. 一.网页不安全 1.用fiddl ...
- java 四舍五入 保留n为数
double x1 = 0.026;String format = String.format("%.2f", x1);System.out.println(format); St ...
- clickhouse入门到实战及面试
第一章. clickhouse入门 一.ClickHouse介绍 ClickHouse(开源)是一个面向列的数据库管理系统(DBMS),用于在线分析处理查询(OLAP). 关键词:开源.面向列.联机分 ...
- Centos7安装jupyter notebook
安装python3 查看当前python版本 [root@iz1i4qd6oynml0z /]# python -V Python 2.7.5 安装python3以及检查python3的版本 yum ...
- Python 如何随机打乱列表(List)排序
场景: 现在有一个list:[1,2,3,4,5,6],我需要把这个list在输出的时候,是以一种随机打乱的形式输出. 专业点的术语:将一个容器中的数据每次随机逐个遍历一遍. 注意:不是生成一个随机的 ...