锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Redis学习

时间:2023-12-27 12:07:02 sc连接器挂掉的原因

本博客根据黑马Redis教程学习笔记,链接如下

一、Redis常用指令

//启动容器 docker run -d -p 6379:6379 -it   --name="myredis"  redis 输入密码: auth 密码 //进入redis容器 docker exec -it myredis  redis-cli //退出 quit exit //清屏 clear //获得帮助, 可以使用Tab键来切换 help 命令名称 help @组名 

二、数据类型

所有的key都为String讨论数据类型的类型value的类型

1、String

基本操作

//设置String set key value mset key1 value1 key2 value2... //设置生命周期 setex key seconds value   //得到String get key  mget key1 key2...  //删除String del key  ///在字符串后面添加字符,如果有,就补在后面,如果没有,就新建 append key value 

string 类型数据的扩展操作

String作为数值的操作

///增长指令,只有当value只有数字才能增长 incr key   incrby key increment   incrbyfloat key increment   //减少指令,有当value减少数字 decr key   decrby key increment 
  • string在redis内部存储默认是字符串,遇到增减操作时incr,decr时会转成数值型进行计算。
  • redis所有的操作都是原子性的,采用单线程在处理所有业务时,命令是一个接一个地执行的,因此无需考虑并发数据的影响。
  • 注:如果原始数据不能转换为数值或超过数值,则按数值操作的数据redis 上限范围的数值,将报错。 9223372036854775807(java中long型数据最大值,Long.MAX_VALUE)

tips:

  • redis控制数据库表主键id,数据库表主键提供生成策略,保障数据库表的主键唯一性
  • 该方案适用于所有数据库,并支持数据库集群

指定生命周期

////设置数据的生命周期,单位 秒 setex key seconds value ////设置数据的生命周期,单位 毫秒 psetex key milliseconds value 

tips

  • redis 控制数据的生命周期,通过数据是否失效来控制业务行为,适用于所有具有及时性限制的操作

命名规范

img

2、Hash

基本操作

//插入(如果有同名field,会被覆盖) hset key field value hmset key field1 value1 field2 value2... //插入(如果有同名field,不会被覆盖) hsetnx key field value  //取出 hget key field hgetall key  //删除 hdel key field1 field2...  //获取field数量 hlen key  //检查是否存在 hexists key field  ///在哈希表中获取所有字段名或字段值  hkeys key hvals key  ///设置指定字段的数值数据,增加指定范围内的值  hincrby key field increment  hdecrby key field increment 

hash 类型数据操作注意事项

  • hash类型下的value只能存储字符串,不允许存储其他数据类型,没有嵌套。如果数据未获取到, 对应的值为(nil)
  • 每个 hash 可以存储 2^32 - 1 个键值
  • hash该类型非常接近对象的数据存储形式,并且可以灵活除对象的属性。hash设计的初衷不是为了存储大量的对象而设计的,切记不要滥用,更不可以将hash作为对象列表使用
  • hgetall 如果内部是,操作可以获得所有属性field过多,遍历整体数据效率会很低,数据访问有可能成为瓶颈

3、List

  • 数据存储需求:存储多个数据,区分数据进入存储空间的顺序
  • 所需的存储结构:存储空间保存多个数据,并通过数据反映进入顺序
  • list类型:保存多个数据,底层采用双向链表存储结构
  • 元素有序,可重

基本操作

//添加修改数据,lpush从左边加,rpush从右边加 lpush key value1 value2 value3... rpush key value1 value2 value3...  ///查看数据, 从左到右检查. 如果不知道list有多少元素,end值可为-1,代表倒数第一元素 //lpush先进元素放在最后,rpush先进元素放在前面 lrange key start end //得到长度 llen key ////取出相应索引的元素 lindex key index  //获取并移除元素(从list移除左或右) lpop key rpop key 

拓展操作

///在规定的时间内获取和删除数据,b=block,给定时间,如果在指定时间内放置元素,则删除 blpop key1 key2... timeout brpop key1 key2... timeout  //移除指定元素 count:移除的个数 value:移除的值。 从左侧移除多个相同元素时 lrem key count value 

注意事项

  • list保存在中的数据都是string数据总容量有限,最多2^32 - 1 个元素 (4294967295)。
  • list它有索引的概念,但通常用于操作数据队列以入队的形式出队(rpush, rpop)操作,或以进出栈的形式(lpush, lpop)操作
  • 所有数据操作结束索引设置为-1 (倒数第一元素)
  • list数据可以分页操作。通常,第一页的信息来自list,以数据库的形式加载第二页和更多信息

4、Set

  • 不重复和无序

基本操作

//添加元素 sadd key member1 member2...  ///检查元素 smembers key  ///去除元素 srem key member  ///检查元素个数 scard key  ///检查某个元素是否存在 sismember key member 

扩展操作

//从set中任意选出count个元素 srandmember key count  //从set中任意选出count并去除个元素 spop key count  ///两集交集,并集,差集 sinter key1 key2... sunion key1 key2... sdiff key1 key2...  //求两个set交集、并集、差集,放另一个set中 sinterstore destination key1 key2... sunionstore destination key1 key2... sdiffstore destination key1 key2...  / smove source destination key 

5sorted_set

  • 不重但有序(score)
  • 新的存储需求:数据排序有利于数据的有效展示,需要提供一种可以根据自身特征进行排序的方式
  • 需要的存储结构:新的存储模型,可以保存可排序的数据
  • sorted_set类型:在set的存储结构基础上添加可排序字段

基本操作

//插入元素, 需要指定score(用于排序)
zadd key score1 member1 score2 member2

//查看元素(score升序), 当末尾添加withscore时,会将元素的score一起打印出来
zrange key start end (withscore)
//查看元素(score降序), 当末尾添加withscore时,会将元素的score一起打印出来
zrevrange key start end (withscore)

//移除元素
zrem key member1 member2...

//按条件获取数据, 其中offset为索引开始位置,count为获取的数目
zrangebyscore key min max [withscore] [limit offset count]
zrevrangebyscore key max min [withscore] [limit offset count]

//按条件移除元素
zremrangebyrank key start end
zremrangebysocre key min max
//按照从大到小的顺序移除count个值
zpopmax key [count]
//按照从小到大的顺序移除count个值
zpopmin key [count]

//获得元素个数
zcard key

//获得元素在范围内的个数
zcount min max

//求交集、并集并放入destination中, 其中numkey1为要去交集或并集集合的数目
zinterstore destination numkeys key1 key2...
zunionstore destination numkeys key1 key2...

注意

  • min与max用于限定搜索查询的条件
  • start与stop用于限定查询范围,作用于索引,表示开始和结束索引
  • offset与count用于限定查询范围,作用于查询结果,表示开始位置数据总量

拓展操作

//查看某个元素的索引(排名)
zrank key member
zrevrank key member

//查看某个元素索引的值
zscore key member
//增加某个元素索引的值
zincrby key increment member

注意事项

  • score保存的数据存储空间是64位,如果是整数范围是-9007199254740992~9007199254740992
  • score保存的数据也可以是一个双精度的double值,基于双精度浮点数的特征,可能会丢失精度,使用时候要慎重
  • sorted_set 底层存储还是基于set结构的,因此数据不能重复,如果重复添加相同的数据,score值将被反复覆盖,保留最后一次修改的结果

三、通用指令

1、Key的特征

  • key是一个字符串,通过key获取redis中保存的数据

2、Key的操作

基本操作

//查看key是否存在
exists key

//删除key
del key

//查看key的类型
type key

拓展操作(时效性操作)

//设置生命周期
expire key seconds
pexpire key milliseconds

//查看有效时间, 如果有有效时间则返回剩余有效时间, 如果为永久有效,则返回-1, 如果Key不存在则返回-2
ttl key
pttl key

//将有时限的数据设置为永久有效
persist key

拓展操作(查询操作)

//根据key查询符合条件的数据
keys pattern

查询规则

拓展操作(其他操作)

//重命名key,为了避免覆盖已有数据,尽量少去修改已有key的名字,如果要使用最好使用renamenx
rename key newKey
renamenx key newKey

//查看所有关于key的操作, 可以使用Tab快速切换
help @generic

3、数据库通用操作

数据库

  • Redis为每个服务提供有16个数据库,编号从0到15
  • 每个数据库之间的数据相互独立

基本操作

//切换数据库 0~15
select index

//其他操作
quit
ping
echo massage

拓展操作

//移动数据, 必须保证目的数据库中没有该数据
mov key db

//查看该库中数据总量
dbsize

三、Jedis

JAVA操作Redis需要导入jar或引入Maven依赖

<dependencies>
        <dependency>
            <groupId>redis.clientsgroupId>
            <artifactId>jedisartifactId>
            <version>2.9.0version>
        dependency>
    dependencies>

1、Java操作redis的步骤

  • 连接Redis
//参数为Redis所在的ip地址和端口号
Jedis jedis = new Jedis(String host, int port)
  • 操作Redis
//操作redis的指令和redis本身的指令几乎一致
jedis.set(String key, String value);
  • 断开连接
jedis.close();

2、配置工具

  • 配置文件
redis.host=47.103.10.63
redis.port=6379
redis.maxTotal=30
redis.maxIdle=10
  • 工具类
public class JedisUtils { 
        
    private static  JedisPool jp = null;
    private static String host;
    private static int maxTotal;
    private static int maxIdle;
    static { 
        
        ResourceBundle rb = ResourceBundle.getBundle("redis");
        host = rb.getString("redis.host");
        int port = Integer.parseInt(rb.getString("redis.port"));
        maxTotal = Integer.parseInt(rb.getString("redis.maxTotal"));
        maxIdle = Integer.parseInt(rb.getString("redis.maxIdle"));
        JedisPoolConfig jpc = new JedisPoolConfig();
        jpc.setMaxTotal(maxTotal);//最大连接数
        jpc.setMaxIdle(maxIdle);//活动连接数
        jp = new JedisPool(jpc,host,port);
    }
    public static Jedis getJedis(){ 
        

        return jp.getResource();
    }
}

案例

package com.jzt.jedisStudy;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisDataException;

public class Service { 
        
    String id ;
    int num;
    public Service(String id,int num){ 
        
        this.id = id;
        this.num = num;
    }
    //控制单元
    public void service(){ 
        
        Jedis jedis = new Jedis("localhost", 6379);
        String value = jedis.get("compid:"+id);
        //判断该值是否存在
        try { 
        
        	//不限次用户不走下面判断
            if(value == null){ 
        
                //不存在
                jedis.setex("compid:"+id,5,Long.MAX_VALUE - num + "");
            }else{ 
        
                //存在,自增,调用业务
                Long val = jedis.incr("compid:"+id);
                business(id,num - (Long.MAX_VALUE - val));
            }
        }
        catch (JedisDataException e){ 
        
                System.out.println("使用到达上限,请升级会员");
                return;
        }
        finally { 
        
            jedis.close();
        }
    }
    //业务操作
    public void business(String id,Long val){ 
        
        System.out.println("用户:" +id + "业务操作执行:" + val + "次");
    }

}
class MyThread extends Thread{ 
        
    Service sc;
    int num;
    public MyThread(String id,int num){ 
        
        sc  = new Service(id,num);
    }
    @Override
    public void run() { 
        
        while(true){ 
        
            sc.service();
            try { 
        
                Thread.sleep(100L);
            } catch (InterruptedException e) { 
        
                e.printStackTrace();
            }
        }
    }
}
class Main{ 
        
    public static void main(String[] args) { 
        
        MyThread mt1 = new MyThread("初级用户",10);
        MyThread mt2 = new MyThread("高级用户",20);
        mt1.start();
        mt2.start();
    }
}

Linux

重新生成配置文件,不带注释

cat redis.conf | grep -v "#" | grep -v "^$" > redis-6379.conf

保留如下配置:

redis-server conf/redis-6379.cnf

开多个端口的redis:记得更改端口

redis-server conf/redis-6380.cnf

客户端启动:

redis-cli -p 6380

四、持久化

Redis容器配置redis.conf

  • redis容器里边的配置文件是需要在创建容器时映射进来的

    停止容器:docker container stop myredis
    删除容器:docker container rm myredis
    
  • 重新开始创建容器

    1. 创建docker统一的外部配置文件
    
    mkdir -p docker/redis/{conf,data}
    
    2. 在conf目录创建redis.conf的配置文件
    
    touch /docker/redis/conf/redis.conf
    
    3. redis.conf文件的内容需要自行去下载,网上很多
    
    4. 创建启动容器,加载配置文件并持久化数据
    
    docker run -d --privileged=true -p 6379:6379 -v /docker/redis/conf/redis.conf:/etc/redis/redis.conf -v /docker/redis/data:/data --name myredis redis redis-server /etc/redis/redis.conf --appendonly yes
    
  • 文件目录

    /docker/redis
    

1、简介

什么是持久化?

利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化。

为什么要持久化

防止数据的意外丢失,确保数据安全性

持久化过程保存什么

  • 将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据
  • 将数据的操作过程进行保存,日志形式,存储操作过程,存储格式复杂,关注点在数据的操作过程

2、RDB

RDB启动方式——save

  • 命令

    save
    
  • 作用

    手动执行一次保存操作

RDB配置相关命令

  • dbfilename dump.rdb
    • 说明:设置本地数据库文件名,默认值为 dump.rdb
    • 经验:通常设置为dump-端口号.rdb
  • dir
    • 说明:设置存储.rdb文件的路径
    • 经验:通常设置成存储空间较大的目录中,目录名称data
  • rdbcompression yes
    • 说明:设置存储至本地数据库时是否压缩数据,默认为 yes,采用 LZF 压缩
    • 经验:通常默认为开启状态,如果设置为no,可以节省 CPU 运行时间,但会使存储的文件变大(巨大)
  • rdbchecksum yes
    • 说明:设置是否进行RDB文件格式校验,该校验过程在写文件和读文件过程均进行
    • 经验:通常默认为开启状态,如果设置为no,可以节约读写性过程约10%时间消耗,但是存储一定的数据损坏风险

RDB启动方式——save指令工作原理

注意save指令的执行会阻塞当前Redis服务器,直到当前RDB过程完成为止,有可能会造成长时间阻塞,线上环境不建议使用

RDB启动方式——bgsave

  • 命令

    bgsave
    
  • 作用

    手动启动后台保存操作,但不是立即执行

RDB启动方式 —— bgsave指令工作原理

注意bgsave命令是针对save阻塞问题做的优化。Redis内部所有涉及到RDB操作都采用bgsave的方式,save命令可以放弃使用,推荐使用bgsave

bgsave的保存操作可以通过redis的日志查看

docker logs myredis

RDB启动方式 ——save配置

  • 配置

    save second changes
    
  • 作用

    满足限定时间范围内key的变化数量达到指定数量即进行持久化

  • 参数

    • second:监控时间范围
    • changes:监控key的变化量
  • 配置位置

    conf文件中进行配置

RDB启动方式 ——save配置原理

注意

  • save配置要根据实际业务情况进行设置,频度过高或过低都会出现性能问题,结果可能是灾难性的
  • save配置中对于second与changes设置通常具有互补对应关系(一个大一个小),尽量不要设置成包含性关系
  • save配置启动后执行的是bgsave操作

RDB启动方式对比

RDB优缺点

  • 优点
    • RDB是一个紧凑压缩的二进制文件,存储效率较高
    • RDB内部存储的是redis在某个时间点的数据快照,非常适合用于数据备份,全量复制等场景
    • RDB恢复数据的速度要比AOF很多
    • 应用:服务器中每X小时执行bgsave备份,并将RDB文件拷贝到远程机器中,用于灾难恢复
  • 缺点
    • RDB方式无论是执行指令还是利用配置,无法做到实时持久化,具有较大的可能性丢失数据
    • bgsave指令每次运行要执行fork操作创建子进程,要牺牲掉一些性能
    • Redis的众多版本中未进行RDB文件格式的版本统一,有可能出现各版本服务之间数据格式无法兼容现象

3、AOF

AOF概念

  • AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令,以达到恢复数据的目的。与RDB相比可以简单描述为改记录数据为记录数据产生的过程
  • AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式

AOF写数据过程

AOF写数据三种策略(appendfsync)

  • always
    • 每次写入操作均同步到AOF文件中,数据零误差,性能较低,不建议使用
  • everysec
    • 每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高建议使用,也是默认配置
    • 在系统突然宕机的情况下丢失1秒内的数据
  • no
    • 由操作系统控制每次同步到AOF文件的周期,整体过程不可控

AOF功能开启

  • 配置

    appendonly yes|no
    
    • 作用
    • 是否开启AOF持久化功能,默认为不开启状态
  • 配置

    appendfsync always|everysec|no
    
    • 作用
      • AOF写数据策略

AOF重写

作用

  • 降低磁盘占用量,提高磁盘利用率
  • 提高持久化效率,降低持久化写时间,提高IO性能
  • 降低数据恢复用时,提高数据恢复效率

规则

  • 进程内已超时的数据不再写入文件

  • 忽略

    无效指令

    ,重写时使用进程内数据直接生成,这样新的AOF文件

    只保留最终数据的写入命令

    • 如del key1、 hdel key2、srem key3、set key4 111、set key4 222等
  • 对同一数据的多条写命令合并为一条命令

    • 如lpush list1 a、lpush list1 b、 lpush list1 c 可以转化为:lpush list1 a b c
    • 为防止数据量过大造成客户端缓冲区溢出,对list、set、hash、zset等类型,每条指令最多写入64个元素

如何使用

  • 手动重写

    bgrewriteaof
    
  • 自动重写

    auto-aof-rewrite-min-size size 
    auto-aof-rewrite-percentage percentage
    

工作原理

AOF自动重写

  • 自动重写触发条件设置

    //触发重写的最小大小
    auto-aof-rewrite-min-size size 
    //触发重写须达到的最小百分比
    auto-aof-rewrite-percentage percent
    
  • 自动重写触发比对参数( 运行指令info Persistence获取具体信息 )

    //当前.aof的文件大小
    aof_current_size 
    //基础文件大小
    aof_base_size
    
  • 自动重写触发条件

工作原理

缓冲策略

AOF缓冲区同步文件策略,由参数appendfsync控制

  • write操作会触发延迟写(delayed write)机制,Linux在内核提供页缓冲区用 来提高硬盘IO性能。write操作在写入系统缓冲区后直接返回。同步硬盘操作依 赖于系统调度机制,列如:缓冲区页空间写满或达到特定时间周期。同步文件之 前,如果此时系统故障宕机,缓冲区内数据将丢失。
  • fsync针对单个文件操作(比如AOF文件),做强制硬盘同步,fsync将阻塞知道 写入硬盘完成后返回,保证了数据持久化。

4、RDB VS AOF

RDB与AOF的选择之惑

  • 对数据非常

    敏感

    ,建议使用默认的

    AOF

    持久化方案

    • AOF持久化策略使用everysecond,每秒钟fsync一次。该策略redis仍可以保持很好的处理性能,当出现问题时,最多丢失0-1秒内的数据。
    • 注意:由于AOF文件存储体积较大,且恢复速度较慢
  • 数据呈现

    阶段有效性

    ,建议使用RDB持久化方案

    • 数据可以良好的做到阶段内无丢失(该阶段是开发者或运维人员手工维护的),且恢复速度较快,阶段 点数据恢复通常采用RDB方案
    • 注意:利用RDB实现紧凑的数据持久化会使Redis降的很低
  • 综合比对

    • RDB与AOF的选择实际上是在做一种权衡,每种都有利有弊
    • 如不能承受数分钟以内的数据丢失,对业务数据非常敏感,选用AOF
    • 如能承受数分钟以内的数据丢失,且追求大数据集的恢复速度,选用RDB
    • 灾难恢复选用RDB
    • 双保险策略,同时开启 RDB 和 AOF,重启后,Redis优先使用 AOF 来恢复数据,降低丢失数据

五、Redis事务

1、Redis事务的定义

redis事务就是一个命令执行的队列,将一系列预定义命令包装成一个整体(一个队列)。当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰

2、事务的基本操作

  • 开启事务

    multi
    
    • 作用
      • 作设定事务的开启位置,此指令执行后,后续的所有指令均加入到事务中
  • 取消事务

    discard
    
    • 作用
      • 终止当前事务的定义,发生在multi之后,exec之前
  • 执行事务

    exec
    
    • 作用
      • 设定事务的结束位置,同时执行事务。与multi成对出现,成对使用

3、事务操作的基本流程

4、事务操作的注意事项

定义事务的过程中,命令格式输入错误怎么办?

  • 语法错误
    • 指命令书写格式有误 例如执行了一条不存在的指令
  • 处理结果
    • 如果定义的事务中所包含的命令存在语法错误,整体事务中所有命令均不会执行。包括那些语法正确的命令

定义事务的过程中,命令执行出现错误怎么办?

  • 运行错误
    • 指命令格式正确,但是无法正确的执行。例如对list进行incr操作
  • 处理结果
    • 能够正确运行的命令会执行,运行错误的命令不会被执行

注意:已经执行完毕的命令对应的数据不会自动回滚,需要程序员自己在代码中实现回滚。

5、基于特定条件的事务执行

  • 对 key 添加监视锁,在执行exec前如果key发生了变化,终止事务执行

    watch key1, key2....
    
  • 取消对所有key的监视

    unwatch
    

分布式锁

  • 使用 setnx 设置一个公共锁

    //上锁
    setnx lock-key value
    //释放锁
    del lock-key
    
    • 利用setnx命令的返回值特征,有值(被上锁了)则返回设置失败,无值(没被上锁)则返回设置成功
    • 操作完毕通过del操作释放锁

注意:上述解决方案是一种设计概念,依赖规范保障,具有风险性

分布式锁加强

  • 使用 expire 为锁key添加时间限定,到时不释放,放弃锁

    expire lock-key seconds
    pexpire lock-key milliseconds
    
  • 由于操作通常都是微秒或毫秒级,因此该锁定时间不宜设置过大。具体时间需要业务测试后确认。

    • 例如:持有锁的操作最长执行时间127ms,最短执行时间7ms。
    • 测试百万次最长执行时间对应命令的最大耗时,测试百万次网络延迟平均耗时
    • 锁时间设定推荐:最大耗时120%+平均网络延迟110%
    • 如果业务最大耗时<<网络平均延迟,通常为2个数量级,取其中单个耗时较长即可

六、删除策略

1、数据删除策略

  • 定时删除
  • 惰性删除
  • 定期删除

时效性数据的存储结构

  • Redis中的数据,在expire中以哈希的方式保存在其中。其value是数据在内存中的地址,filed是对应的生命周期

数据删除策略的目标

在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成整体redis性能的下降,甚至引发服务器宕机或内存泄露

2、三种删除策略

定时删除

  • 创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
  • 优点:节约内存,到时就删除,快速释放掉不必要的内存占用
  • 缺点:CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量
  • 总结:用处理器性能换取存储空间 (拿时间换空间

惰性删除

  • 数据到达过期时间,不做处理。等下次访问该数据时
    • 如果未过期,返回数据
    • 发现已过期,删除,返回不存在
  • 优点:节约CPU性能,发现必须删除的时候才删除
  • 缺点:内存压力很大,出现长期占用内存的数据
  • 总结:用存储空间换取处理器性能 (拿空间换时间)

定期删除

3、逐出算法

**当新数据进入redis时,如果内存不足怎么办? **

  • Redis使用内存存储数据,在执行每一个命令前,会调用freeMemoryIfNeeded()检测内存是否充足。如果内存不满足新加入数据的最低存储要求,redis要临时删除一些数据为当前指令清理存储空间。清理数据的策略称为逐出算法
  • 注意:逐出数据的过程不是100%能够清理出足够的可使用的内存空间,如果不成功则反复执行。当对所有数据尝试完毕后,如果不能达到内存清理的要求,将出现错误信息。

影响数据逐出的相关配置

  • 最大可使用内存

    maxmemory
    

    占用物理内存的比例,默认值为0,表示不限制。生产环境中根据需求设定,通常设置在50%以上。

  • 每次选取待删除数据的个数

    maxmemory-samples
    

    选取数据时并不会全库扫描,导致严重的性能消耗,降低读写性能。因此采用随机获取数据的方式作为待检测删除数据

  • 删除策略

    maxmemory-policy
    

    达到最大内存后的,对被挑选出来的数据进行删除的策略

影响数据逐出的相关配置

LRU:最长时间没被使用的数据

LFU:一段时间内使用次数最少的数据

数据逐出策略配置依据

  • 使用INFO命令输出监控信息,查询缓存 hit 和 miss 的次数,根据业务需求调优Redis配置

七、高级数据类型

1、Bitmaps

基础操作

  • 获取指定key对应偏移量上的bit值

    getbit key offset
    
  • 设置指定key对应偏移量上的bit值,value只能是1或0

    setbit key offset value
    

扩展操作

  • 对指定key按位进行交、并、非、异或操作,并将结果保存到destKey

    bitop op destKey key1 [key2...]
    
    • and:交
    • or:并
    • not:非
    • xor:异或
  • 统计指定key中1的数量

    bitcount key [start end]
    

2、HyperLogLog

基数

  • 基数是数据集去重后元素个数
  • HyperLogLog 是用来做基数统计的,运用了LogLog的算法

基本操作

  • 添加数据

    pfadd key element1, element2...
    
  • 统计数据

    pfcount key1 key2....
    
  • 合并数据

    pfmerge destkey sourcekey [sourcekey...]
    

相关说明

  • 用于进行基数统计,不是集合,不保存数据,只记录数量而不是具体数据
  • 核心是基数估算算法,最终数值存在一定误差
  • 误差范围:基数估计的结果是一个带有 0.81% 标准错误的近似值
  • 耗空间极小,每个hyperloglog key占用了12K的内存用于标记基数
  • pfadd命令不是一次性分配12K内存使用,会随着基数的增加内存逐渐增大
  • Pfmerge命令合并后占用的存储空间为12K,无论合并之前数据量多少

3、GEO

基本操作

  • 添加坐标点

    geoadd key longitude latitude member [longitude latitude member ...] 
    georadius key longitude latitude radius m|km|ft|mi [withcoord] [withdist] [withhash] [count count]
    
  • 获取坐标点

    geopos key member [member ...] 
    georadiusbymember key member radius m|km|ft|mi [withcoord] [withdist] [withhash] [count count]
    
  • 计算坐标点距离

    geodist key member1 member2 [unit] 
    geohash key member [member ...]
    

八、主从复制

1、简介

多台服务器连接方案

  • 提供数据方:master
    • 主服务器,主节点,主库
    • 主客户端
  • 接收数据的方:slave
    • 从服务器,从节点,从库
    • 从客户端
  • 需要解决的问题
    • 数据同步
  • 核心工作
    • master的数据复制到slave中

主从复制

主从复制即将master中的数据即时、有效的复制到slave中

特征:一个master可以拥有多个slave,一个slave只对应一个master

职责:

  • master:
    • 写数据
    • 执行写操作时,将出现变化的数据自动同步到slave
    • 读数据(可忽略)
  • slave:
    • 读数据
    • 写数据(禁止

2、作用

  • 读写分离:master写、slave读,提高服务器的读写负载能力
  • 负载均衡:基于主从结构,配合读写分离,由slave分担master

相关文章