https://learnku.com/articles/22363
https://learnku.com/articles/25331
基于缓存 key-value形式
解决缓存雪崩
在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期
缓存穿透 (查询一个一定不存在的数据)
使用布隆过滤器
拦截器
读取信息一般步骤
查询缓存,有直接读取;
没有,查询数据库,写入缓存
返回数据
缓存与数据一致
设置过期时间
更新缓存
特点
数据持久化、
五种数据类型
字符串 string
简单字符串、复杂字符串(json、xml)、数字(整形、浮点型)、甚至二进制文件(图片、视
频、 音频),但值不能超过512MB
列表 list
存储多个有序字符串
哈希(hash)
集合(set)
有序集合(sort set)
持久化
RDB 持久化,将 redis 在内存中的的状态保存到硬盘中,相当于备份数据库状态
AOF 持久化(Append-Only-File),AOF 持久化是通过保存 Redis 服务器锁执行的写状态来记录数据库的。相当于备份数据库接收到的命令,所有被写入 AOF 的命令都是以 redis 的协议格式来保存的。
string 数据语法
| 语法 | 描述 | 使用 | return |
|---|---|---|---|
| set key value | 写入数据 | set name word | ok |
| get key | 查询数据 | get name | value/nil(空) |
| del key | 删除数据 | del name | integer 1 /integer 0 |
| mset key1 value1 key2 value 2 … |
添加/修改多个数据 | mset name hello age 20 |
|
| mget key1 key2 | 获取多个数据 | ![]() |
对应的 value/nil(空) |
| strlen key | 字符串长度 | int | |
| append key value | 追加数据到末尾 有点像函数array_push |
||
| incr key | 数值数据指定增长范围 先 set num 1 同下 |
incr num | (integer)2 |
| incrby key increment | 数值数据指定增长范围 | incrby num 10 | (integer) 11 |
| incrbyfloat key increment | 数值数据指定增长范围 | incrbyfloat num 1.5 | 2.5 |
| decr key | 数值数据指定减少范围 先 set num 2 同下 |
decr num | 1 |
| decrby key | 数值数据指定减少范围 | decr num 2 | 0 |
| setex key second value | 设置数据生命周期 (秒级) 当时间超过 60(秒)后 get key 会返回空 |
setex token 60 qps | ok |
| psetex key millisecond value | 设置数据生命周期 (毫秒级) |
注意事项
运行结果返回 bool ;运行结果值返回 int ; 数据为空 nil 等同 null ;数据最大存储 512MB ;数值最大范围 java 的long;
key设置约定
表名:主键名:主键值:字段名 例如 order:id:123:name
hash 语法
| 语法 | 描述 | 实例 | return |
|---|---|---|---|
| hset key field value | 添加修改数据 | hset user name pqs hset user weight 80 使用写入数据 |
int 0/1 |
| hget key field | 获取数据 | hget user name | pqs |
| hgetall key | 获取全部 key | hgetall user | name qps weight 80 |
| hdel key field1 [field2] | 删除key | hdel user weight | int 0/1 |
| hmset key field1 value1 … | 添加多个数据 | ||
| hmget key field1 … | 获取多个数据 | ||
| hlen key | 统计表中字段数量 | hset user id:3 hlen user |
3 |
| hexists key field | 是否存在指定字段 | hexists user weight | int 0/1 |
| hkeys | 获取key | ||
| hvals | |||
| hsetnx key field value | 如果有值则写入失败; 否则新增key |
hsetnx 01 goods1:num 2 | int 0/1 |
| hincrby key value number | hset p01 g50 20 hincrby p01 g50 -1 |
int 19 |


注意事项
不要把hash 当做对象列表使用,当内部field过多,效率低下
特性
原子性
list数据
| 语法 | 描述 | 实例 | return |
|---|---|---|---|
| lpush key value1 [value2] … | 左边添加数据 | lpush list a lpush list b lpush list c |
int 1 int 2 int3 |
| rpush key value1 [value2] … | 右边添加数据 | rpush test x y z |
int 3 |
| lrange key start stop [reɪndʒ] |
获取数据 lrange test 0 -1 查询所有 |
lrange list 0 2 lrange test 0 2 |
1 c 2 b 3 a 1 x 2 y 3 z |
| lindex key index | 获取数据 | lindex list 0 lindex list 1 lindex test 0 |
c b x |
| llen key | 获取长度 | llen list | int 3 |
| lpop key | 左边删除数据 | lpop list lpop test |
c x |
| rpop key | 右删除数据 | rpop list rpop test |
a z |
| blpop key [key2] timeout | 规定时间内获取并删除左数据 | ||
| brpop key [key2] timeout | 规定时间内获取并删除右数据 | ||
| lrem key count value | 删除指定数据 count 移除个数 |
rpush g1 a b c d lrem g1 1 c |
int 1 |
实例
注意事项
list 保存的是string 数据 数据总容量 2^32-1
list 是有索引操作,队列形式进行入队出队(入栈出栈)操作
set 类型
| 语法 | 描述 | 实例 | return |
|---|---|---|---|
| asdd key val1 val2 | 添加数据 | sadd user qps sadd user qyhn |
int 1 int 1 |
| smembers key | 获取所有数据 | smembers user | |
| srem key val1 val2 | 删除数据 | ||
| scard key | 获取集合总数量 | ||
| sismembers key val1 | 判断是否存在指定值 | ||
| srandmembers key [count] | 随机获取集合中指定数量的数据 | ||
| spop key | 随机获取集合中的某个数据并删除 |
链表数据结构
持久化
确保数据安全
持久化方式
持久化过程保存数据(二进制数据 快照)RDB
命令 save 关键字写入
操作过程(日志)AOF
重启
service redis-server restart 服务 redis - 服务器 重启
对比memcached
两者对比:
redis提供数据持久化功能,memcached无持久化;
redis的数据结构比memcached要丰富,能完成场景以外的事情;
memcached的单个key限制在250B,value限制在1MB;redis的K、V都为512MB;当然这些值可以在源码中修改;
memcached数据回收基于LRU算法,Redis提供了多种回收策略(包含LRU),但是redis的回收策的过期逻辑不可依赖,没法根据是否存在一个key判断是否过期。但是可根据ttl返回值判断是否过期;
memcached使用多线程,而redis使用单线程,基于IO多路复用实现高速访问。所以可以理解为在极端情况下memcached的吞吐大于redis。
结论:<br /> 普通KV场景:memcached、redis都可以。<br /> 从功能模块单一这个角度考虑的话,推荐memcached,只做cache一件事。<br /> 在KV长度偏大、数据结构复杂(比如取某个value的一段数据)、需要持久化的情况下,用redis更适合:但是在使用redis的时候单个请求的阻塞会导致后续请求的积压,需要注意
设计秒杀
$ttl = 4;$random = mt_rand(1,1000).'-'.gettimeofday(true).'-'.mt_rand(1,1000);$lock = fasle;while (!$lock) {$lock = $redis->set('lock', $random, array('nx', 'ex' => $ttl));}if ($redis->get('goods.num') <= 0) {echo ("秒杀已经结束");//删除锁if ($redis->get('lock') == $random) {$redis->del('lock');}return false;}$redis->decr('goods.num');echo ("秒杀成功");//删除锁if ($redis->get('lock') == $random) {$redis->del('lock');}return true;
限制时间请求次数 例:每 30 分钟只能访问100次
$num = $redis->incr($key); \\对存储在指定key的数值执行原子的加1操作if($num == 1){$redis->expire($key, 30*60);}if($num > 100) {return false;}

