【原创】 Redis应用

Reids + PHP应用
一、消息队列原理、概念
1.1 消息队列概念
a、队列结构的中间件
b、消息放入后不需要立即处理
c、由订阅者/消费者按照顺序处理
1.2 核心结构
1.3 应用场景
冗余:比如订单系统,需要严格的做数据转换和记录,消息队列可以持久化的把这些信息存储在消息队列中
解耦:比如两套系统,彼此独立
流量削峰:秒杀和抢购,配合缓存来使用消息队列
异步通信:
排序保证:
1.4 常见队列实现优缺点
队列介质:
1.5 消息处理触发机制
二、解耦案例-队列处理订单系统和配送系统
2.1 架构设计
2.2 程序流程
三、流量削峰案例 - Redis的List类型实现秒杀
3.1 架构设计
3.2 代码设计
用户秒杀的代码
模拟秒杀生成的uid参数
读取redis队列,数据写进数据库的代码
四、RabbitMQ - 更专业的消息系统实现方案
4.1 RabbitMQ的架构和原理
4.2 RabbitMQ安装
4.3 Work Queue
五、PHP秒杀系统整体设计
5.1 本质
高并发、高可用
5.2 原理知识介绍
减而治之:
a、CND原理
b、nginx限流
c、异步队列
分而治之:
a、nginx负载均衡
5.3 特征与难点分析
特征:
a、写强一致性:卖出的商品、计数的数量一致
b、读弱一致性:比如12306抢票的时候确实看到有票,下单的时候却没了
难点:
a、极致性能的实现
b、高可用的保证
5.4 秒杀系统核心实现
1. 极致性能的读服务实现:
a场景、订单详情页读取,通过CDN加速方式减轻服务器压力
b场景、实时读取总库存
2. 极致性能的写服务实现:
a场景:扣库存
3. 极致性能的排队进度查询实现
比如12306抢票,可能会有一个排队的进度,用户频繁去查询还剩多少分钟,这么一个服务
4. 链路流量如何优化
比如流量到达LVS层、接入层、service层
5.5 兜底-高可用
1. 高可用的标准
2. 请求链路中每层高可用的实现原理
3. 限流、一键降级、自动降级实现
5.6 接口压力测试
平时使用最多的ab压测工具,通过 “Requests per second:”这一项数据值分析接口和机器性能状态
5.7 限流
1. nginx限流配置
区别:上面一个限制并发数,下面一个限制单个ip请求数
2. 限流算法介绍
a、令牌桶算法
b、漏桶算法
5.8 CND介绍
提高读源站性能一大利器
CND原理:
CDN - 普通域名访问
CDN - DNS解析原理
注意:不同地域的客户端访问同一个域名的时候,拿到的CND地址是不一样的,基本是距离客户端比较近的CDN服务器地址,通过这样的方式来实现一定的加速;而CDN服务器也会把源站上的内容做一定时间的缓存,通过这样的方式来降低源服务的qps,提高读服务性能
5.9 大型网站架构
5.10 秒杀系统使用场景
5.10.1 秒杀系统 - 特点介绍
a、抢购人数远远多于库存,读写并发极大
b、库存少,有效写少
c、写强一致性,商品不能超卖,也就是说库存减少量与创建订单量必须一致的
d、读一致性要求并不高
5.10.2 秒杀系统 - 难点
稳定性难:
a、高并发下,某个小依赖可能直接造成雪崩
b、流量预期难精确,过高也会造成雪崩
c、分布式集群,机器多,出故障的概率高
准确性难:
a、库存、抢购成功数、创建订单数之间一致性
高性能难:
a、有限成本下需要做到极致的性能
5.10.3 秒杀系统 - 架构原则
稳定性:
高性能:
5.11 秒杀服务核心实现
5.11.1 该怎样去设计?
基本需求:
基本需求 - 场景举例:
基本需求 - 扣库存方案:
预扣库存方案实现:
极高并发下怎么做到单服务极致性能:
I/O主要包含:
无I/O怎么做?
普通下单业务实现:
去I/O后的业务实现:
并发量过大单服务还是扛不住怎么办?
本地减库存,集群机器挂了怎么办?怎么保证不少卖?
单服务扣库存实现:
1、初始化库存到本地库存
2、本地减库存,成功则进行统一减库存,失败则返回
3、统一减库存成功则写入mysql,异步创建订单
4、告知用户抢购成功
创建订单、支付订单服务:
基本需求 - 读取商品信息:
【原创】 Redis入门、第二部分

Reids数据库基础知识
一、Redis高级
1.1 通用命令
1.1.1、key通用指令
key特征:key是一个字符串,通过key获取redis中保存的数据
key应该设计哪些操作?
对于key自身的状态相关操作,例如:删除,判定存在,获取类型等
对于key有效性相关操作,例如:有效期设定,判定是否有效,有效状态的切换等
对于key快速查询操作,例如:按指定策略查询key
key基本操作:
a、删除指定key:del key
b、获取key是否存在:exists key
c、获取key的类型:type key
key扩展操作(时效性):
a、为指定key设置有效期:expire key seconds
b、为指定key设置有效期:pexpire key milliseconds
c、为指定key设置有效期:expireat key timestamp
d、为指定key设置有效期:pexpireat key milliseconds-timestamp
e、获取key的有效时间:ttl key
ttl获取key过期时间,如果一个key不存在,则返回-2;如果一个key存在,则返回-1;如果一个设置了有效期,则返回剩余有效时间
f、获取key的有效时间:pttl key
g、切换key从时效性转换为永久性:persist key
key通用操作:
a、查询key:keys pattern(匹配的语法格式)
key其他操作:
a、为key改名:rename key newkey
b、如果key不存在则为key改名:renamenx key newkey
c、对所有key排序,只是排了序,没有动原来数据:sort key
1.2 数据库通用指令
1.2.1、看如下问题
1.2.2、db基本操作
a、切换数据库:select index
b、控制台打印:echo xxx
c、测试客户端与服务端连通性:ping
d、移动数据:move key db
数据清除操作(谨慎、小心操作):
e、清除当前数据库:flushdb
f、清除所有数据库:flushall 不要用这个指令,0-15号库数据全部干掉...
g、查看数据容量:dbsize
二、Redis持久化
2.1 意外的断电
2.2 自动备份
2.3 什么是持久化
利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化
2.4 为什么要持久化
防止数据的意外丢失,确保数据的安全性
2.5 持久化过程保存什么
2.6 持久化方案一 ,RDB启动方式--save指令
持久化的命令:save
作用:手动执行一次,保存一次
2.6.1 RDB相关配置
RDB启动方式----save指令相关配置
1、设置dbfilename
2、设置rdbcompression 值为yes
2.6.2 数据恢复过程演示
杀掉进程后再启动,上图的3420进程,redis又重新运行
数据已经恢复
2.6.3 save指令工作原理
1、假如4个指令都要执行,并且按照客户端1--4的顺序先后到达并执行
2、到达以后假如是下面的指令排序
3、指令执行
4、save指令有可能造成阻塞,拉低服务器性能,线上环境不建议使用save指令
2.7 持久化方案二 ,RDB启动方式--bgsave指令
数据量过大,单线程方式造成效率过低如何处理?
2.7.1 持久化命令
指令:bgsave
作用:手动启动后台保存操作,但不是立即执行
操作:
执行bgsave命令前
执行bgsave命令后,文件大小已经变了
查看文件内容,已经增加了addr值chengdu
2.7.2 bgsave指令工作原理
1、下达指令
2、调用linux的fork函数,生成子进程,由子进程去完成
在日志文件去查看这个过程
注意:bgsave命令是针对save命令阻塞问题做的优化,save命令是立马执行,并且加入到任务执行序列中,bgsave采用的是fork创建的子进程来完成的这个过程;redis内部所有涉及到RDB操作都采用bgsave方式,save命令可以放弃使用
2.7.3 bgsave指令相关配置
2.8 持久化方案三 ,RDB启动方式--自动执行
2.8.1 配置
指令配置:save second changes
作用:满足限定时间范围内key的变化数量达到指定数量即进行持久化
参数:second -- 监控时间范围 changes -- 监控key的变化
位置:在conf文件中进行配置,不要乱设置,设置不合理也是灾难性的;second和changes一般遵循前面大后面小,前面小后面大
范例:
注意:只要是在设定的时间范围内,满足条件的key数量发生变化(包括添加、修改),就会自动保存数据
2.8.2 RDB启动方式save配置原理
2.9 RDB三种启动方式对比
2.10 RDB特殊启动方式
2.11 RDB的优点与缺点
2.12 AOF简介
RDB的弊端:
1、存储数据量较大,效率较低,基于快照的思想,每次读写都是全部数据,当数据量巨大时,侠侣非常低
2、大数据量下的IO性能较低
3、基于fork创建子进程,内存产生额外消耗
4、宕机带来的数据丢失,快照思想存储是基于某个时间点的数据,无法做到即时的数据存储
解决思路:
1、不写全数据,仅记录部分数据
2、改记录数据为记录操作过程
3、对所有操作均进行记录,排除丢失数据的风险
AOF概念:
1、AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的,与RDB相比,可以简单的描述为:改记录数据为记录数据产生的过程
2、AOF主要作用是解决了数据持久化的实时性,目前已经是redis持久化的主流方式,优先使用AOF方式
2.13 AOF写数据过程
2.14 AOF写数据的三种策略
2.15 AOF功能开启
配置:appendonly yes|no,默认是no
作用:是否开启AOF持久化功能,默认为不开启状态
配置AOF策略:appendfsync always | everysec | no
作用:AOF写数据策略
案例演示:
AOF其它相关配置:
2.16 AOF写数据遇到的问题
AOF重写:
随着命令不断写入AOF,文件会越来越大,为了解决这个问题,redis引入了AOF重写机制压缩文件体积。AOF文件重写是将redis进程内的数据转化为写命令同步到新AOF文件的过程。简单说就是将对同一个数据的若干个命令执行结果转化成最终结果数据对应的指令进行记录
AOF重写的作用:
降低磁盘占用量,提高磁盘利用率
提高持久化效率,降低持久化写时间,提高IO性能
降低数据恢复用时,提高数据恢复效率
AOF重写的规则:
AOF重写的方式:
1、手动重写:bgrewriteaof
案例演示:
第一步、
第二步、
第三步、重写
第四步、
AOF手动重写---bgrewriteaof指令工作原理
2、自动重写:
auto-aof-rewrite-min-size size
auto-aof-rewrite-percentage percentage
注意:info指令,查看当前redis运行属性值!!!
AOF工作流程:
基于everysec开启重写
2.17 RDB和AOF的区别
2.18 持久化应用场景
三、Redis事务
3.1 事务简介
redis事务就是一个命令执行的队列,将一系列预定义命令包装成一个整体(一个队列)。当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰;在开发中一般不使用redis事务,作为一个了解就好。
一个队列,一次性、顺序性、排他性的执行一系列命令
3.2 事务的基本操作
开启事务:multi
作用:设定事务的开始位置,此指令执行后,后续的所有指令均加入到事务中
执行事务:exec
作用:设定事务的结束位置,同时执行事务。与multi成对出现,成对使用
注意:加入事务的命令暂时进入到任务队列中,并没有立即执行,只有执行exec命令才开始执行
3.3 事务定义过程中发现问题了怎么处理?
取消事务:discard
作用:终止当前事物的定义,发生在multi命令之后,exec命令之前
3.4 事务的工作流程
set指令:
multi开启事务:
来一个set指令加入队列:
再来一个del指令加入队列:
来一个exec指令:执行了exec指令以后,队列消失
来一个discard指令:直接销毁掉队列里面的指令集
3.5 事务定义过程中,命令格式输入错误怎么办
3.6 事务-锁
一、业务场景一介绍
解决方案:
对key添加监视,在执行exec前如果key发生了变化,终止事务执行
watch key1 [key2,...]
注意:开启watch监控要在开启事务之前,开启watch指令监控的东西如果发生改变,定义的事务将不会执行 ,返回一个nil
取消对key的所有监视:
unwatch
二、业务场景二介绍
基于特定条件的事务执行--分布式锁:
1、使用setnx设置一个公共锁,不存在key才能设置成功,存在则不能设置也不能替换 setnx lock-key value
利用setnx命令返回值的特征,有值则返回设置失败,无值则返回设置成功
对于返回设置成功的,拥有控制权,进行下一步的具体业务操作;对于返回设置失败的,不具有控制权,排队或等待
2、操作完毕使用del释放锁
3.7 事务-死锁
一、业务场景一介绍
解决方案:
使用expire为锁key添加时间限定,到时不释放,放弃锁
expire lock-key second
pexpire lock-key milliseconds
由于操作通常都是微妙或毫秒级,因此该锁定时间不宜设置过大,具体时间需要业务测试后确定
注意这个参数选择!!!
四、删除策略
4.1 redis数据特征
redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过ttl指令获取其状态
4.2 redis数据删除策略
数据删除策略的目标:
在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成redis性能下降,甚至引发服务器宕机或者是内存泄漏
数据删除的方式:
定时删除:
惰性删除:
定期删除:
4.3 redis逐出算法
4.4 服务器配置
服务器端基础配置:
日志配置:
注意:日志级别开发期设置为verbose,生产环境中设置为notice,简化日志输出量,降低写日志IO频度
客户端配置:
多服务器快捷配置:
五、高级数据类型
5.1 搁置
六、主从复制
6.1 互联网“三高”架构
高并发
高性能
高可用
多台服务器连接方案:
主从复制:
高可用集群:
主从复制的作用:
主从复制工作流程:
1、建立连接工作流程
2、实现连接
方式一、客户端发送命令
master端
slave端
方式二、启动服务器参数
master端:
slave端:
方式三、服务器配置
master端:
slave端:
3、主从断开连接
master端:
slave端:先执行下面命令
4、授权访问
七、哨兵
7.1 待完善
八、集群
8.1 待完善
九、企业级解决方案
9.1 缓存预热
宕机:服务器启动后迅速宕机
问题排查:
1. 请求数量较高
2. 主从之间数据吞吐量较大,数据同步操作频度较高
解决方案:
前置准备工作:
1. 日常例行统计数据访问记录,统计访问频度较高的热点数据
2. 利用LRU的数据删除策略,构建数据留存队列,列如:storm与kafka配合
准备工作:
3. 将统计结果中的数据进行分类,根据级别,redis优先加载级别较高的热点数据
4. 利用分布式多服务器同时进行数据读取,提速数据加载过程
实施:
1. 使用脚本程序固定触发数据预热过程
2. 如果条件允许,使用了CDN(内容分发网络)效果会更好
总结:缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统,避免用户在请求的时候先请求数据库然后再缓存的问题,用户直接查询事先预热的缓存数据!
9.2 缓存雪崩
数据库服务器崩溃(1)
1. 系统平稳运行过程中,忽然数据库连接量激增
2. 应用服务器无法及时处理请求
3. 对外响应408超时,或者响应500错误页面
4. 用户得不到反馈数据,反复刷新页面
5. 请求量越来越大,数据库崩溃
6. 应用服务器崩溃
7. 重启应用服务器无效
8. redis服务器开始崩溃
9. redis集群崩溃
10. 重启数据库后再次被瞬间流量放倒
问题排查:
1. 在一个较短的时间内“缓存中较多的key集中过期”
2. 在此周期内请求访问过期数据,redis未命中,redis向数据库获取数据
3. 数据库同时接收到大量请求无法及时处理
4. redis大量请求被积压,开始出现超时现象
5. 数据库流量增大,数据库崩溃
6. 重启后依然面对缓存中无数据可用
7. redis服务器资源被严重占用,redis服务器崩溃
8. redis集群呈现崩塌,集群瓦解
9. 应用服务器无法及时得到数据响应请求,客户端用户继续刷新,来自客户端的请求数量越来越多,应用服务器崩溃
10. 应用服务器、redis、数据库全部重启,效果依然不理想(重启只是给自己一个心理安慰罢了,redis缓存依然没有数据,必崩)
分析问题
1. 短时间内
2. 大量key集中过期
解决方案(道):
1. 更多的页面静态化处理 (原因是页面过多的数据从缓存取)
2. 构建多级缓存结构:Nginx缓存 + redis缓存 + ehcache缓存(纯Java的进程内缓存框架)
3. 检测mysql严重耗时业务进行优化,对数据库的瓶颈排查:列如超时查询、耗时较高事务等
4. 灾难预警机制,监控redis服务器性能指标
CPU占用,CPU使用率 (雪崩的典型现象CPU比较忙)
内存容量
查询平均响应时间
线程数
5. 限流、降级
短时间内牺牲一些客户体验,限制一部分请求访问,降低应用服务器压力,待业务低速运转后再逐步放开访问
解决方法(术):
1. LRU与LFU切换
2. 数据有效期策略调整
根据业务数据有效期进行错峰,假如A类90分钟,B类80分钟,C类70分钟
过期时间使用固定时间 + 随机值形式,稀释集中到期的key的数量,比如A类某某key90.1,A类另一key90.5等
3. 超热数据使用永久key(区分超热普通热点)
4. 定期维护(自动 + 人工)
对即将过期数据做访问量分析,确认是否延时,配合访问量统计,做热点数据延时
5. 加锁(慎用)
拿到锁的干活,拿不到锁的就拿不到数据
总结:
1. 不管是道的层面还是术的层面,都要去做监控预防,道的话就是平时该怎么去设计,术的话就是出现问题要知道该去动哪些东西
2. 缓存雪崩就是瞬间过期数据量太大,导致对数据库服务器造成压力。如果能有效避免过期时间集中,可以有效解决雪崩现象的出现(约40%),配合其他策略一起使用,并监控服务器的运行数据,根据运行记录做快速调整
9.3 缓存击穿
数据库服务器崩溃(2)
1. 系统平稳运行过程中
2. 数据库连接量瞬间激增
3. redis服务器内key无大量过期
4. redis内存平稳,无波动
5. redis服务器CPU正常
6. 数据库崩溃
问题排查:
1. redis中某个key过期,该key访问量巨大
2. 多个数据请求从服务器直接压到redis后,均未命中
3. redis在短时间内发起了大量对数据库中同一数据的请求
问题分析:
1. 单个key高热数据
2. key过期
解决方案(术):
1. 预先设定:
以电商为例,每个商家根据店铺等级,指定若干款主打产品,在购物节期间,加大此类信息key的时长
注意:不仅仅是购物街当天,以及后续若干天,访问峰值呈现主键降低的趋势
2. 现场调整:
监控访问量,对自然流量激增的数据延长过期时间,或者设置为永久性key
3. 后台刷新数据:
启动定时任务,高峰期来临之前,刷新数据有效期,确保不丢失
4. 二级缓存:
设置不同的失效时间,保障不会同时失效就行 (还是尽量分类设置过期时间,同类的商品key过期时间都加随机值浮动)
5. 加锁:
分布式锁,防止被击穿,但是要注意也是性能瓶颈,慎重! (不太推荐,实在没有办法的时候考虑使用)
总结:
缓存击穿就是单个高热数据过期的瞬间,数据访问量较大,未命中redis后,发起了大量对同一数据的数据库访问,导致对数据库服务器造成压力。应对策略应该在业务数据分析与预防方面进行,配合运行监控测试与及时调整策略,毕竟单个key的过期监控难度较高,配合雪崩处理策略即可。
9.4 缓存穿透
数据库服务器崩溃(3)
1. 系统平稳运行过程中
2. 应用服务器流量随时间增量较大
3. redis服务器命中率随时间逐步降低 (redis命中率降低,对应数据库服务压力变大)
4. redis内存平稳,内存无压力
5. redis服务器CPU占用激增
6. 数据库服务器压力激增
7. 数据库崩溃
问题排查:
1. redis中大面积出现未命中
2. 出现非正常的URL访问
a、假设百度搜索redis关键字
b、点击关键字
c、得到正常的URL访问结果
d、假设随意修改URL的文章id编号进行访问
e、得到这么个结果,redis未命中,直接进到数据库查询
问题分析:
1. 获取的数据在数据库中也不存在,数据库查询未得到对应的数据
2. redis获取到null数据未进行持久化,直接返回
3. 下次此类数据到达,重复上述过程
4. 出现黑客攻击 (黑客想办法在穿透redis来对数据库进行攻击,这种攻击不是为了搞数据,通过大量无效URL访问让服务器无法命中,然而给数据库带来较大的流量,导致数据库被整崩掉)
解决方案(术):
1. 缓存null
对查询结果为null的数据进行缓存(长期使用,定期清理),设定短时限,例如30秒-60秒,最高5分钟,时间太久就导致内存泄露 (不是一个有效的解决方案,要是一下来几十万个数据,内存占用短时间瞬间起来)
内存泄露:程序在申请内存后无法释放已经申请的内存空间,一次性内存泄露可以忽略,但内存泄露堆积后果很严重,memory leak(内存泄露)最终会导致 out of memory(内存不足) ,这块内存不释放,就不能再使用了,就叫这块内存泄露了。
内存溢出:是程序在申请内存时,没有足够的内存空间供其使用。比如你需要10M的内存空间,内存空间只剩8M,这就会出现内存溢出。就是说分配的内存不足以放下数据项序列,称为内存溢出。
2. 白名单策略
提前预热各种分类数据id对应bitmaps,id作为bitmaps的offset,相当于设置了数据白名单。当加载正常数据时放行,加载异常数据时直接拦截(效率偏低)。
使用布隆过滤器
3. 实施监控
实时监控redis命中率(业务正常范围时,通常会有一个波动值)与null数据的占比
非活动时段波动:通常检测3-5倍,超过5倍纳入重点排查对象
活动时段波动:通常检测10-50倍,超过50倍纳入重点排查对象
根据倍数不同,启动不同的排查流程,然后使用黑名单进行防控
4. key加密
问题出现后,临时启动防灾业务key,对key进行业务层传输加密服务,设定校验程序,过来的key校验
列如每天随机分配60个加密串,挑选2到3个,混淆到页面数据id中,发现key不满足访问规则,驳回数据访问
总结:
1. 缓存击穿访问了不存在的数据,跳过了合法数据的redis数据缓存阶段,每次访问数据库,导致对数据库服务器造成压力。通常此类数据的出现量是一个较低的值,当出现此类情况以毒攻毒,及时报警。应对策略应该在临时预案防范方面多做文章
2. 无论是白名单还是黑名单,都是对整体系统的压力,警报解除后尽快移除
9.5 性能指标监控
监控指标
1. 性能指标
2. 内存指标
3. 基本活动指标
4. 基本活动指标
5. 基本活动指标
监控方式:
命令:
benchmark
monitor命令:打印服务器调试信息
slowlog命令:
【原创】 Redis入门、第一部分

Reids数据库基础知识
一、Redis简介
1.1 问题现象
1.2 NoSql
NoSql:Not-Only-Sql(泛指非关系型的数据库),“作为关系型数据库的补充”
作用:应对给予海量用户和海量数据前提下的数据处理问题
特征:不遵循SQL标准、远超于SQL性能、不支持ACID
NoSql应用场景:对数据高并发的读写、海量数据的读写、对数据高可扩展性
NoSql不适合的场景:需要事务支持、基于SQL的结构化查询,处理复杂的关系
常见的NoSql数据库:Redis、memcache、HBase、MongoDB
1.3 Redis
概念:Redis(Remote Dictionary Sever) 使用C语言开发的一个开源的高性能键值对(key-value)数据库
1.4 Redis特征
redis是一个单线程+多路I/O复用机制;memcached是多线程+锁机制
1.5 Redis的应用
1.6 Redis在windows下的安装
1.7 命令行模式工具使用思考
功能性命令
清楚屏幕信息
帮助信息查询
退出指令
二、Redis基础操作
2.1 信息添加
功能:设置key、value数据
命令:set key value
2.2 信息查询
功能:根据key查询对应的value,如果不存在,返回 nil
命令:get key
2.3 清除屏幕信息
功能:清除屏幕中的信息
命令:clear
2.4 帮助
功能:获取命令帮助文档,获取组中所有命令信息名称
命令:help 命令名称 help @组名(help 空格 table)
2.5 退出
功能:退出客户端
命令:quit exit esc(这个玩意儿慎用)
三、Redis数据类型
3.1 数据业务使用场景介绍
3.2 数据存储类型基本介绍
Redis有5大数据存储类型,分别是string、hash、list、set、sorted_set
redis数据存储格式:
redis自身是一个Map,其中所有的数据都采用key:value的形式存储
数据类型:指的是存储的数据类型,也就是value部分的类型,key部分永远都是字符串
3.2.1 string类型
存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
存储数据的格式:一个存储空间保存一个数据
存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用
string类型数据的基本操作:
操作成功提示integer 1 操作失败提示integer 0
a、添加/修改数据:set key value
b、获取数据:get key
c、删除数据:del key
d、添加/修改多个数据:mset key1 value1 key2 value2
e、获取多个数据:mget key1 key2
f、获取数据字符个数(字符串长度):strlen key
g、追加信息到原始信息后部(如果原始信息存在就追加,否则新建):append key value
string类型数据的扩展操作:
a、设置数值数据增加指定范围的值
指定键的value值加1:incr key
指定键的value值加上指定整数值:incrby key increment
指定键的value值加上指定浮点数值:incrbyfloat key increment
b、设置数值数据减少指定范围的值
decr key
decrby key decrement
c、设置数据具有指定的生命周期
setex key seconds value
psetex key milliseconds value
为key设置过期时间 expire key seconds
获取值的范围 getrange key start end
string作为数值操作:
string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值类型进行计算
string的所有操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发带来的数据影响
注意:按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis数值上限范围,将报错
提示:
1、redis用于控制数据库表主键id,为数据库表主键提供生成策略,保证数据库表的主键唯一性;此方案适用所有数据库,且支持数据库集群
2、redis控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作
string类型数据操作注意事项:
1、数据操作不成功的反馈与数据正常操作之间的差异
2、数据未获取到
nil等同于null
3、数据最大存储量
string类型数据,单个value最大存储量512MB
string类型应用场景:
说明: 表名:主键字段:主键值:说明字段(粉丝、关注量等等...)
用json形式存放一组数据
注意:数据库中的热点数据key命名案例
3.2.2 hash类型
新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
需要的存储结构:一个存储空间保留多个键值对数据
hash类型数据的基本操作
a、添加/修改数据:hset key field value
b、获取数据:hget key field hgetall key
c、删除数据:hdel key field1 field2
d、添加/修改多个数据:hmset key field1 value1 field2 value2
e、获取多个数据:hmget key field1 field2
f、获取hash表中字段的数量:hlen key
g、获取hash表中是否存在指定的字段:hexists key field
hash类型数据的扩展操作
a、获取hash表中所有的字段名或字段值:hkeys key hvals key
b、设置指定字段的数值数据增加指定范围的值:hincrby key field increment(指定字段增加整数) 、 hincrbyfloat key field increment(指定字段增加浮点数)
hash类型数据操作注意事项:
1、hash类型下的value只能存储字符串,不允许存储其它类型数据,不存在嵌套现象。如果数据未获取到,对应的值为 nil
2、每个hash可以存储2的32次方-1个键值对
3、hash类型十分贴近对象的数据存储形式,并且可以灵活的添加删除对象属性,但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用
4、hgetall操作可以获取全部属性,如果内部field过多,遍历整体数据效率就会低,有可能成为数据访问瓶颈
hash类型应用场景:
1、电商网站购物车设计与实现(属于买家)
当前仅仅是将数据存储到了redis中,并没有起到加速的作用,商品信息还需要二次查询数据库
hsetnx key field value 在此场景的使用:如果当前key中对应的field有值,就什么都不做;如果没值,我就把它加进去!!!
2、双十一活动,销售手机充值卡的商家对移动、联通、电信的30元、50元100元商品推出的抢购活动,比如商品抢购上限1000单(属于卖家)
业务场景:
string存对象(json)与hash存对象的优缺点,string讲究整体性,数据一次性整体操作,要么一次性更新要么一次性读取,以读为主;而hash因为有field字段把属性隔离开,讲究更新操作更具有灵活性,以更新为主!!! 开发的时候根据需求灵活设置数据类型
3.2.3 list类型
数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
list类型:保存多个数据,底层使用双向链表存储结构实现,哪边都能进 哪边都能出
list类型数据的基本操作
a、添加/修改数据:lpush key value [value ...] rpush key value [value ...]
b、获取数据/查询数据:
lrange key start stop 获取列表指定范围的元素,lrange key start stop ,这里的start代表开始,stop代表结束,当stop为-1的时候表示取到最后一个值,当stop为-2的时候,表示取到倒数第二个值,以此类推;lrange key 0 -1,表示全部取出
左边进去的1 2 3 ,左边查询出来3 2 1
右边进去的 1 2 3,左边查询出来 1 2 3
c、lindex key index ,通过索引从列表中获取/查询元素
d、llen key ,获取链表的长度
e、从左边“移除”数据(移出、弹出),lpop key,当队列中数据移出完以后会删掉key
f、从右边“移除”数据(移出、弹出), rpop key,当队列中数据移出完以后会删掉key
list类型数据的扩展操作
规定时间内获取并移除数据
a、 blpop key [key ...] timeout 删除并获取列表的第一个元素,或阻止直到有可用的元素
拿不出来就一直在那儿等,直到设置时间到,返回nil
b、 brpop key [key ...] timeout 删除并获取列表的第一个元素,或阻止直到有可用的元素
list类型数据操作注意事项:
1、list中保存的数据都是string类型的,数据总量是有限的,最多2的32次方-1个元素(4294967295)
2、list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作
3、获取全部数据操作结束的索引设置为-1
4、list可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加载
list类型应用场景:
1、微信朋友圈点赞,要求按照点赞顺序现实点赞好友信息
从列表中删除元素,移除指定数据,lrem key count value
2、新浪微博、腾讯微博中个人用户的关注列表需要按照用户的关注顺序进行展示,粉丝列表需要将最近关注的粉丝列在前面
3.2.4 set类型
数据存储需求:存储大量的数据,在查询方面提供更高的效率
需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询
set类型:与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的
set类型数据的基本操作
a、添加数据:sadd key member [member ...]
b、获取全部数据:smembers key
c、删除数据:srem key member [member ...]
d、获取集合数据总量:scard key
e、判断集合中是否包含指定数据:sismember key member
set类型应用场景:
1、应用场景举例1
set类型数据的扩展操作:
a、随机获取集合中指定数量的数据:srandmember key [count]
b、随机获取集合中的某个数据并将该数据移出集合:spop key
提示:redis应用于随机推荐类信息检索,列如热点歌单推荐,热点新闻推荐,热卖旅游路线推荐,应用APP推荐,大V推荐等
2、应用场景举例2
c、求两个集合的交集:sinter key [key ...]
d、求两个集合的并集:sunion key [key ...]
e、求两个集合的差集:sdiff key [key ...]
f、求两个集合的交集、并集、差集并存储到指定的集合中
g、将指定数据从原始集合中移动到目标集合中:smove source destination member
提示:
set类型数据注意事项:
1、set类型不允许数据重复,如果添加的数据在set中已经存在,将只保留一份
2、set虽然与hash存储结构相同,但是无法启用hash中存储至的空间
3、应用场景举例3
校验工作:redis提供基础数据还是提供校验结果? 尽量提供基础数据,不在redis数据端做数据校验
4、应用场景举例4
提示:redis应用于同类型数据的快速去重
5、应用场景举例5
3.2.5 sotred_set类型
数据存储需求:数据排序有利于数据的有效显示,需要提供一种可以根据自身特征进行排序的方式
需要的存储结构:新的存储模型,可以保存可排序的数据
sorted_set类型:在set的存储结构基础上添加可排序字段
sorted_set数据的基本操作:
a、添加数据:zadd key [NX|XX] [CH] [INCR] score member [score memb
b、获取全部数据(从小到大):zrange key start stop [WITHSCORES]
加了参数withscores以后的结果:
c、获取全部数据(从大到小):zrevrange key start stop [WITHSCORES]
d、删除数据:zrem key member [member ...]
e、按条件获取数据(从小到大):zrangebyscore key min max [WITHSCORES] [LIMIT offset count]
f、按条件获取数据(从大到小):zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]
附加limit条件查询:
g、按条件索引删除数据:zremrangebyrank key start stop
h、按条件删除数据:zremrangebyscore key min max
i、获取集合数据总量:zcard score
j、统计集合某个范围的数据:zcount key min max
k、集合交集操作:zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AG
sorted_set类型应用场景:
1、应用场景举例1
m、获取数据对应的索引(由小到大):zrank key member
n、获取数据对应的索引(由大到小):zrank key member
o、score值得获取
p、score值修改
提示:
sorted_set类型数据注意事项:
1、score保存的数据存储空间是64位,如果整数范围是-9007199254740992~9007199254740992
2、score保存的数据也可以是一个双精度的double值,基于双精度浮点数的特征,可能会丢失精度,使用时候要慎重
3、sorted_set底层存储还是基于set结构,因此数据不能重复,如果重复添加相同的数据,score将被反复覆盖,保留最后一次修改结果
【原创】 Redis 基本使用

Redis的基本使用
1、Redis基本介绍
1.1、redis 基本介绍
1.2、redis安装和基本使用
1.3、redis的优势
异常快速:Redis速度非常快,每秒能执行约11万集合,约81000条每秒。
支持丰富的数据类型:Redis原生支持最大多数开发人员已经知道的,像列表,集合,分类,散列等数据类型。这使得它非常容易解决各种各样的问题,因为我们知道哪些数据类型问题是可以通过它的处理得更好。
操作原子性:所有Redis的操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。
MultiUtility工具:Redis是一个多实用的工具,可以在一些像缓存,消息,队列用例中使用(Redis原生支持发布/订阅),在应用程序,如Web应用程序的会话,网络页面点击数短期数据等等。
操作原理图:
链接redis:
1.3、redis操作指令一览
2、Redis基本使用
2.1、redis的基本使用
2.3、Redis的CURD
2.3.1、Redis的五大数据类型
String(字符串)、Hash(哈希)、Lish(链表)、集合(Set)、有序集合(Zset)
String基本介绍:
a、String是redis最基本的类型,一个key对应一个value
b、String类型是二进制安全的,除普通字符串外,也可以存放图片等数据;单个value最大值512M
c、set操作,set[如果key存在就相当于修改,如果不存在相当于添加];set key value;
d、get操作,直接 get key键
e、del操作,直接del key键
f、set设置过期时间, setex key 过期时间 value
g、mset同时设置一个或多个 key-value对,如果给定的key已经存在,那么mset会用新值覆盖原来的旧值,格式:mset key1 value1 key2 value2,可以使用mget 获取全部值 也可以单独使用get 指定的键
Hash基本介绍(hash类似golang里面的map):
a、Redis hash是一个键值对集合,每个hash可存储多达2的32次方-1个字段-值对(超过42亿)
b、Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象
c、设置指令格式: hset key field value
d、获取指令格式: hget key field
e、获取所有: hgetall key
f、一次性设置所有:hmset key field value field value ...
g、一次性获取所有:hmget key field field ...
h、删除指定字段:hdel key field
i、hlen统计一个hash有几个元素
j、查看hash表key中,是否存在给定的field字段,指令格式:hexists key field
List(列表)基本介绍:
列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
List本质是个链表,List的元素是有序的,元素的值可以重复。
List数据结构分析:
a、设置一个链表,从左边插入:lpush key value value value ... 依次放入aaa bbb ccc
b、获取链表内容,从左边“取出”(只是取出,链表中还存在这个数据):lrange key start stop ,这里的start代表开始,stop代表结束,当stop为-1的时候表示取到最后一个值,lrange key 0 -1,表示全部取出;依次取出 ccc bbb aaa
c、设置一个链表,从右边插入:rpush key value value value ... 依次放入ddd eee
此刻再从左边取出, 看看数据结构:
d、从链表左边“弹出”(从链表中弹出移走数据):lpop key
e、从链表右边“弹出”(从链表中弹出移走数据):rpop key
f、删除整个链表:del key
注意事项:
a、lindex :按照索引下标获得元素(从左到右,编号从0开始)
b、LLEN key :返回列表key的长度,如果key不存在,则key被解释为一个空列表,返回0
c、List数据,可以从左 或者从右插入添加
d、如果值全移除,对应的键也就消失了
Set(集合)基本介绍:
Redis的Set是string类型的无序集合,底层是Hash Table数据结构,Set也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复
a、添加数据到集合中:sadd key member member member ... (member:成员)
b、从集合中取出所有数据:smembers key
c、判断值是否是成员:sismember key member
d、删除集合中指定的成员:srem key member
注意事项:
a、元素的值不能重复
【原创】 Win10环境下安装redis5.0.10

Windows环境下安装redis
1、安装Redis客户端
1.1 下载地址:https://github.com/tporadowski/redis/releases
1.2 redis指令地址:http://redisdoc.com/
2、开启Redis服务
2.1 来到redis解压目录,使用命令cmd进入到命令行窗口
2.2 开启redis服务
3、下载redis扩展
3.1 下载地址:http://pecl.php.net/package/redis
下载版本根据安装的客户端redis版本选择
3.2 点击版本厚点的DLL,下载另一个扩展
根据上图PHP版本选择下载扩展
4、安装扩展
4.1 解压扩展,复制到:D:\wamp326\bin\php\php7.3.33\ext目录下
4.2 修改php.ini文件,在如下位置添加extension=php_redis.dll重启
5、重启wampserver服务
5.1 访问phpinfo()搜索redis,发现如下扩展则安装成功
6、windows环境下的开机自启动
6.1 启动redis服务,进入到redis安装目录,输入命令: redis-server.exe redis.windows.conf
6.2 打开一个新的cmd,输入命令: redis-server --service-install redis.windows.conf
6.3 重启,查看计算机服务
6.4 启动一个客户端,测试redis服务
6.5 自启动与关闭自启动:
redis-server --service-start
redis-server --service-stop
7、使用PHP连接redis
7.1 PHP连接redis测试
【原创】 Linux环境配置PHP-Redis扩展

Linux环境下配置Redis扩展
1、PHP7.2.33配置Redis扩展
1.1 新建php-redis目录
1.2 进到php-redis目录下载扩展
wget https://pecl.php.net/get/redis-5.2.1.tgz
1.3 解压
tar -zxvf redis-5.2.1.tgz
1.4 在解压目录下执行phpize,若是没有生成configure,则安装zutoconf,然后再执行phpize
1.5 编译安装
./configure --with-php-config=/www/server/php/72/bin/php-config --enable-redis
make && make install
1.6 写入php.ini文件并重启
然后重启PHP systemctl restart php-fpm
1.7 测试
【原创】 Linux环境下安装redis6.0.8

Linux环境下安装redis
1、安装Redis
1.1 新建redis目录
1.2 下载redis6.0.8安装包
wget http://download.redis.io/releases/redis-6.0.8.tar.gz
1.3 解压
tar -zxvf redis-6.0.8.tar.gz
1.4 安装C语言编译环境
查看和升级gcc版本(gcc版本过低需要升级,如果是高版本可以省略此步骤)
更新命令如下:
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
再次查看gcc版本:
1.5 编译
先进入到redis-6.0.8目录
make
1.6 安装
make install
进入到redis-6.0.8目录下面的src目录执行
也可以直接make && make install
查看默认安装位置
1.7 测试,前台启动
1.8 查看redis进程
ps -ef|grep redis
1.9 配置后台启动,快捷启动命令
vim /root/software/redis-6.0.8/redis.conf
注释bind127.0.0.1,否则只有本机才能访问
修改 daemonize no 为daemonize yes 开启守护进程模式,设置为后台运行,进程不会终止,除非手动kill该进程
设置外网可链接,protected-mode值改为no
保护模式,该模式控制外部网是否可以连接redis服务,默认是yes,所以默认我们外网是无法访问的,如需外网连接rendis服务则需要将此属性改为no。
设置redis密码,打开注释,后面设置自己的密码
保存退出
其他配置:
监听端口:
日志、持久化文件保存目录:
数据库数量,设置为1代表只使用一个库,默认16个库,0~15
设置redis能够使用的最大内存
日志文件,默认为空,不记录日志,可以指定日志文件名
1.10 将redis设置成开机自启动(后台启动)
a、首先创建几个目录
b、将redis安装目录的redis.conf复制一份到/etc/redis目录下,命名为6379.conf
c、修改6379.conf的logfile 为/var/log/redis/6379.log
d、修改6379.conf的dir ./ 为 dir /var/log/redis/data ,用来做redis持久化,保存后缀为.rdb的文件
e、将安装的redis目录下utils目录下的redis_init_script文件复制到/etc/init.d/下面,命名为redis
f、修改/etc/init.d/redis文件
g、将redis服务设置开机自启动 chkconfig redis on
h、重启reboot, 查看进程 ps -ef|grep redis
1.11 本机登录redis
auth 密码
远程链接不上使用以下命令启动redis:redis-server /root/software/redis-6.0.8/redis.conf
1.12 redis的启动
1.13 redis客户端连接