Redis笔记
帮助手册
https://github.com/phpredis/phpredis#rpop
一、Redis 简介
Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:
1.Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
2.Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
3.Redis支持数据的备份,即master-slave模式的数据备份。
二、Redis 优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
- Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
- Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
三、Redis与其他key-value存储有什么不同?
四、Redis 安装
下载文件:
将文件解压至指定盘符
使用命令进入目录
redis-server.exe redis.windows.conf 不要关闭这一屏 也不要结束
redis-cli.exe 从新起一个页面
将redis加入到windows的服务中(service和loglevel前都是两个-)开机自启动
有可能是:redis-server --service-install redis.windows-service.conf --loglevel verbose
也有可能是:
redis-server --service-install redis.windows.conf
再次 win+R,运行 services.msc
找到Redis,右键启动,如图。
图形界面工具
三、Redis 数据类型
掌握redis有5中数据类型 ,能够通过项目的需求使用不同的类型 ,用的比较多的类型为
String hash list zset[带分数的]
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(
Sort set:有序集合)。
数据类型 | 存储的值 | 读写能力 |
String | 可以是字符串、整数统称为元素 | 对字符串的操作 对整数类型的加减 |
List | 一个序列集合且每个节点都包好了一个元素 | 序列两端推入,或弹出元素,修检、查找或移除元素 |
Set | 各不相同的元素 | 从集合中插入或删除元素 |
Hash | 有key和value的散列组, | 按照key进行添加删除 |
zset | 带分数的score-value有序集合 | 集合中插入按照分数进行查找 |
(一)String(字符串)
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
实例
注意:一个键最大能存储512MB。
赋值 SET key value [EX seconds] [PX milliseconds] [NX|XX]
set age 18 设置键名为 age 的值为18
mset age 18 sex 男 设置多个
取值 GET key
get name 获取指定的key的值
mget number name 获取多个值
先获取在设置 getset name zhangsan将给定key设置为value的值,并返回key的旧值
删除 del name 删除key的值 如果有执行成功返回1 失败返回0
加一 incr number 指定key的值自增1
减一 decr number 指定key的值减1
指定加值 incrby number 5 将key所存储的值加上给定的增加值
指定减值 decrby number 3 将key所存储的值加上给定的减值
拼凑 append a 123
Getrange 返回 key 中字符串值的子字符
(二)Hash(哈希)
redis hash 是一个键值(key=>value)对集合。
redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
实例
DEL runoob 用于删除前面测试用过的 key,不然会报错:(error) WRONGTYPE Operation agai
实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。
每个 hash 可以存储 232 -1 键值对(40多亿)。
赋值 hset hash1 name zhangsan 设置给定的key的value
hmset hash2 name lisi age 18 sex nan 设置多个
取值 hget hash1 name 获取存储在哈希表中指定字段的值
hmget hash2 name age sex 获取多个
hgetall hash2 获取所有的
删除 hdel hash2 name 删除指定的字段
del hash2 删除指定所有
增加 hincrby hash1 age 5
hexists hash1 age 查看哈希表 key 中,指定的字段是否存在。
hlen hash1 获取哈希表中字段的数量
hkeys hash1 获取所有哈希表中的字段
hvals hash1 获取哈希表中所有值
(三)List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
实例
列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。
两端添加 lpush mylist a b c 将一个或多个元素插入到列表头部
rpush mylist a b c 将一个或多个元素插入到列表尾部
查看 lrange mylist 0 3 获取列表指定范围内的元素
开始 结束 结束-1 为全部
两端弹出 lpop mylsit 移除并获取列表的第一个值【从头删除】
rpop mylsit 移除并获取列表的最后一个值【从尾删除】
获取列表个数 llen mylist 获取列表的长度
仅当存【这个变量有的时候】在时才插入 lpushx mylist q 当mylist存在的时候,将p插入到头部【插入头部】
仅当存在时才插入 rpushx mylist q 当mylist存在的时候,将p插入到尾部【插入尾部】
删除 lrem mylist 2 a 删除 2个a
Lrem list 3 2 删除3个2元素
在指定元素前【后】插入元素 linsert mylist before[after] b 11; 在b之后(之前)插入元素
Rpoplpush mylist mylist2 从一个列表中弹出一个值压入到另一个列表中
(四)Set(集合)
Redis的Set是string类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
实例
添加 sadd myset a b c
删除 srem myset a b
查看 smembers myset
是否存在 sismember myset a myset中a是否存在
差集 sdiff myset1 myset2
交集 sinsert myset1 myset2
并集 sunion myset myset2
长度 scard myset
随机返回成员 srandmemberset myset
差集存入变量 sdiffstore myset1 myset2 myset3 将myset2和myset3中的相差的值存入myset1中
交集存入变量 sinterstore myset1 myset2 myset3 将myset2和myset3中的交集的值存入myset1中
并集存入变量 sunionstore myset1 myset2 myset3 将myset2和myset3中的并差的值存入myset1中
跟踪唯一,访问博客的ip地址存入到set中
注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。
集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。
(五)zset(sorted set:有序集合)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
添加 Zadd mysort 70 张三 80 李四 90王五
取值 zscore myset 张三
Zcard mysort 成员数量
删除 zrem mysort 张三 李四
Zrevrand mysort 0 4 按照范围删除
Zremrangbyscore mysort 80 100 删除80到100之间的分数
范围查找 zrang mysort 0 -1全部的内容
Zrem mysort 0 -1 全部
Zrang mysort 0 -1 withscores 元素对应的分数
Zrangbyscore mysort 1 100 withscores
zincrby mysort 3 list 给list+3
Zcount mysort 80 90 统计80 到90之间有多少
Key的通用操作
Type score1 判断redis的类型
Expire score1 100 设置score1的过期时间 [到过期时间删除该变量]
Ttl score 所剩的时间
Exists email 判断是否存在,存在是1 不存在是 0
del email 删除元素
redis的事务
Redis 事务
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 批量操作在发送exec命令前被放入队列缓存。
- 收到 exec命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
- 开始事务。
- 命令入队。
- 执行事务。
Redis的两种持久化
RDB方式 [以时间为节点定期写入] 默认的方式 在指定时间内将数据写入到磁盘当中
save 900 1 每900秒一个key发生变化时写入
save 300 10 每300秒10个key发生改变的时候写入
save 60 10000 每 60秒有1万个key发生改变时写入
写入到 目录下 dump.rdb
AOF方式 以日志的形式写入到磁盘当中,会记录所处理的每一个操作
appendfsync always 每次修改的时候写入,
#appendfsync everysec 每秒写入
# appendfsync no 不同步
window中安装PHP的扩展
查看你PHP的版本
下载对应的版本
Redis.dll扩展 http://pecl.php.net/package/redis
Igbinary.dll的扩展 https://windows.php.net/downloads/pecl/releases/igbinary/
将下载的文件 dll pdb文件放入环境php版本中的ext文件夹下
修改配置文件
; php_redis
extension=php_igbinary.dll
extension=php_redis.dll
重启环境
php操作redis讲解
建立连接
创建Redis客户端
Tp5中使用redis
1、 修改配置文件 conf.php
1.什么是缓存穿透
一般的缓存系统,都是按照key值去缓存查询,如果不存在对应的value,就应该去DB中查找 。这个时候,如果请求的并发量很大,就会对后端的DB系统造成很大的压力。这就叫做缓存穿透。关键词:缓存value为空;并发量很大去访问DB。
造成的原因
1.业务自身代码或数据出现问题;
2.一些恶意攻击、爬虫造成大量空的命中,此时会对数据库造成很大压力。
解决方法
1.设置布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,
从避免了对底层存储系统的查询压力。
2. 如果一个查询返回的数据为空,不管是数据不存在还是系统故障,我们仍然把这个结果进行缓存,但是它的过期时间会很短
最长不超过5分钟。
二、雪崩
1.什么是雪崩
因为缓存层承载了大量的请求,有效的保护了存储 层,但是如果缓存由于某些原因,整体不能够提供服务,于是所有的请求,就会到达存储层,存储层的调用量就会暴增,造成存储层也会挂掉的情况。缓存雪崩的英文解释是奔逃的野牛,指的是缓存层当掉之后,并发流量会像奔腾的野牛一样,大量后端存储。
存在这种问题的一个场景是:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,大量数据会去直接访问DB,此时给DB很大的压力。
2.解决方法
(1)设置redis集群和DB集群的高可用,如果redis出现宕机情况,可以立即由别的机器顶替上来。这样可以防止一部分的风险。
(2)使用互斥锁
在缓存失效后,通过加锁或者队列来控制读和写数据库的线程数量。比如:对某个key只允许一个线程查询数据和写缓存,其他线程等待。单机的话,可以使用synchronized或者lock来解决,如果是分布式环境,可以是用redis的setnx命令来解决。
(3)不同的key,可以设置不同的过期时间,让缓存失效的时间点不一致,尽量达到平均分布。
(4)永远不过期
redis中设置永久不过期,这样就保证
了,不会出现热点问题,也就是物理上不过期。
(5)资源保护
使用netflix的hystrix,可以做各种资源的线程池隔离,从而保护主线程池。