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 获取多个数据 image.png 对应的 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

    image.png
    image.png
    注意事项
    不要把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

    实例
    image.png
    注意事项
    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。

    1. 结论:<br /> 普通KV场景:memcachedredis都可以。<br /> 从功能模块单一这个角度考虑的话,推荐memcached,只做cache一件事。<br /> KV长度偏大、数据结构复杂(比如取某个value的一段数据)、需要持久化的情况下,用redis更适合:但是在使用redis的时候单个请求的阻塞会导致后续请求的积压,需要注意

    设计秒杀

    1. $ttl = 4;
    2. $random = mt_rand(1,1000).'-'.gettimeofday(true).'-'.mt_rand(1,1000);
    3. $lock = fasle;
    4. while (!$lock) {
    5. $lock = $redis->set('lock', $random, array('nx', 'ex' => $ttl));
    6. }
    7. if ($redis->get('goods.num') <= 0) {
    8. echo ("秒杀已经结束");
    9. //删除锁
    10. if ($redis->get('lock') == $random) {
    11. $redis->del('lock');
    12. }
    13. return false;
    14. }
    15. $redis->decr('goods.num');
    16. echo ("秒杀成功");
    17. //删除锁
    18. if ($redis->get('lock') == $random) {
    19. $redis->del('lock');
    20. }
    21. return true;
    1. 限制时间请求次数 例:每 30 分钟只能访问100
    1. $num = $redis->incr($key); \\对存储在指定key的数值执行原子的加1操作
    2. if($num == 1){
    3. $redis->expire($key, 30*60);
    4. }
    5. if($num > 100) {
    6. return false;
    7. }