• redis入门学习


    1.redis基础

    redis有16个数据库 默认使用第0个 
    默认端口6379
    redis基于内存 瓶颈是机器内存和网络带宽 单线程的
    
    为什么redis单线程效率高?
    redis所有数据在内存上 多线程cpu会上下文切换 耗时操作 
    对于内存系统来说 多次读写在一个cpu上效率最高
    
    基本命令(记住):
    select 3    //切换到第3号数据库
    dbsize    //查看该数据库存有多少个数据
    keys *    //查看数据库所有的key
    flushdb    //清空该数据库数据
    flushall //清空所有数据库的数据
    exists name //是否存在name这个key 存在1 不存在0
    move name 1 //将name这个key移除 1表示当前库
    expire name 1 //name这个key 10秒后过期
    ttl name    //查看key剩余过期时间
    type name  //查看key的类型

    2.String字符串

    基本命令
    append key "hello"    //往key追加字符串hello key若不存在就新增
    strlen key    //获取字符串长度
    incr key    // 自增1 相当于i++
    incrby key 8 //自增8 相当于i+=8
    decr key    //自减1
    decrby key 8   //自减8
    
    getrange key 0 3  //截取字符串 相当于substring
    setrange key 1 xx //替换字符串 相当于replace
    
    
    //重点(常用)
    setex key 30 "hb"   //添加值并设置过期时间
    setnx key "hb"    //不存在key添加 存在key添加失败(分布式锁中常用到)
    mset k1 v1 k2 v2    //批量添加
    mget k1 k2        //批量获取
    msetnx k2 v2 k3 v3 //同上是批量添加 若k2或k3只要有已存在key就添加失败
    getset key v1    //先取得key的值并设置新的值 

    3.List

    redis的list就是栈 链表 后进先出 push进 pop出 但可以从左或从右添加元素
    list命令基本是l开头的
    
    基本命令
    lpush key  one   //从左边添加元素
    rpush key  one   //从右边添加元素
    lrange key 0 1    //获取起始到终止位置的元素 0 -1是所有的元素
    lpop key     //从左边移除第一个元素
    rpop key    //从右边移除第一个元素
    lindex key 0    //获取下标0的元素
    llen key    //获取list的长度
    lrem key 1 one  //移除list中1个value为one的值
    ltrim key 1 2    //只保留list中下标1到2的值 其它值被删除
    
    rpoplpush key key1    //把key最右边元素剪切到key1中
    exists key        //是否存在key
    lset key 0 value1      //更新操作 将下标0的值替换为value1 下标0无值报错
    linsert key before value1 insvalue  //list中value1的值前加上一个元素 这个元素的值为insvalue.  其中before/after往前/后插入

    4.Set

    set命令基本s开头
    
    基本命令
    sadd myset value1    //添加元素
    smembers myset    //获取set中所有值
    sismember myset value1    //set中是否包含value1这个元素
    scard myset        //获取set元素个数
    srem myset value1    //移除set中指定的元素
    srandmember myset 2  //随机抽选set集合指定个数的元素
    spop myset    //随机删除set中的元素
    smove myset1 myset2 value1    //set集合myset1中的value1剪切移动到myset2中
    sdiff myset myset1    //取第一个集合与第二个集合的差集(1集合有2集合没有)
    sinter myset myset1    //取第一个集合与第二个集合的交集(2个集合都有的元素 共同好友这个做)
    sunion myset myset1    //取并集(2个集合整合)

    5.hash

    hash命令基本h开头
    
    hset myhash key1 value1    //添加hashmap
    hget myhash key1            //获取hashmap
    hmset myhash k1 v1 k2 v2    //批量添加hashmap
    hmget myhash k1 k2            //批量获取hashmap
    hgetall myhash                //获取hash所有值(kv都显示)
    hdel myhash key1        //删除
    
    hlen myhash    //获取hashmap个数
    hexists myhash k1    //hashmap中指定字段是否存在
    hkeys myhash    //获取所有key
    hvals myhash    //获取所有values
    
    hincrby myhash k1 1    //自增1
    hsetnx myhash k1 v1    //不存在创建
    
    存对象如用户对象
     用string: set user:1:name hb
     用hash:  hset user:1 name hb       
    用hash更好一点

    6.zset(有序集合)

    就把它看成linkhashset
    
    基础语法
    基本是z开头
    zadd myzset 1 v1 2 v2    //添加元素(可以批量添加)
    zrange myzset 0 -1    //正序显示所有元素(zrevrange是反序)
    zrangebyscore myzset -inf +inf [withscores]   //按-无穷到+无穷排序显示(inf是无穷的意思 []可选 withscores也打出下标 )
    
    zrem myzset two    //移除元素
    zcard myzset        //获取集合元素个数
    zcount myzset 1 3    //获取指定区间的元素个数
    
    
    与set命令的api基本一致
    应用范围:
        排行榜//数量存下标 能排列显示排行信息

    7.geospatial

    地理位置 可以推算位置信息和距离
    
    命令geo开头
    //南北极无法导入 一般情况下直接下载地理位置信息导入到redis
    
    geoadd mygeo 116.40 39.90 beijin    //添加地理位置
    geoadd mygeo 121.47 31.23 shanghai 121.47 31.23 shanghai1    //也可以批量添加
    geopos mygeo shanghai    //获取指定城市的经纬度
    
    geodist mygeo beijin shanghai km [withcoord]    //两地间距离(m米 km千米 mi英里 ft英尺子) 
    georadius mygeo 120.3 30.2 1000 km [withcoord] [withdist] [count 1]    //获取以指定经纬度为中心半径1000km范围内的元素 
    //withcoord显示元素的坐标 withdist显示到中心的距离 count允许显示元素的个数
    
    georadiusbymember mygeo shanghai 100 km //同上 中心坐标改为指定的元素
    
    
    //geo底层其实就是zset 因此可以用zet命令处理geo
    zrange mygeo 0 -1    //显示地图所有元素
    zrem mygeo shanghai    //移除指定元素

      

    8.Hyperloglog 基数

    基数(不重复的元素)
    如{1,3,5,7,8,7}基数是{1,3,5,7,8}
    应用场景:如网站访问统计人数,同一人多次访问算一人
        传统方式:set保存用户id 存大量用户id比较麻烦 因为目的只是为了计数
        Hyperloglog:基数统计算法 且占用内存固定 只需12kb 但有0.81%错误率
    
    基本语法
    pf开头
    pfadd mypfkey a b c d e d //添加
    pfcount mypfkey        //统计基数数量 5
    pfmerge mypfkey3 mypfkey2 mypfkey1    //mypfkey3的值为mypfkey1和2的并集
    
    
    注:Hyperloglog有容错率0.81% 不允许容错的话就不能用

    8.Bitmaps

    位存储
    操作二进制 只有0和1两种状态
    
    基本命令
    setbit mybit 0 1    //在第一位置添加1
    getbit mybit 0        //获取第一位的值
    bitcount mybit        //统计值为1的数量

    9.事务

    原子性:要么同时成功 要么同时失败 
    一致性:事务的执行使得数据库从一种正确状态转换成另外一种正确状态
    隔离性:在事务正确提交之前,它可能的结果不应该显示给其他事务
    持久性:事务正确提交之后,其结果将永远保存在数据库之中
    
    redis事务不保证原子性 保证一致性 顺序性 排他性
    
    redis事务流程:
    1.开启事务 2.依次输入redis命令 3.执行事务
    
    
    基本命令
    multi    //开启事务
    exec    //事务结束 开始执行
    
    discard    //取消事务 事务队列中的命令都不会执行

    10.乐观锁

    悲观锁:无论什么情况都会加锁
    乐观锁:不会加锁 只有在更新字段的时候会去判断期间是否有人改过数据 用watch监控
    mysql的乐观锁是version监控
    
    如:
    乐观锁付款事务正常流程:
    set money 100
    set out 0
    watch money    //监控money 若money变了 下面事务exec执行失败
    multi
    decrby money 20    
    incrby out 20
    exec        //事务成功会自动解锁
    //如果事务提交失败应该是money被改了 执行下面失败的流程
    unwatch    //解锁
    watch money //再加锁 锁定money的最新值
    ...            //继续把事务走一遍

    11.jedis

    添加依赖:
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>3.2.0</version>
            </dependency>
    
    测试:
    Jedis jedis = new Jedis("127.0.0.1",6379);
    jedis.get("key");
    
    -------------------------------------------------------------------
    
    springboot整合
    springboot2.x后jedis被替换为lettuce
    1.添加依赖:
         <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    2.yml中添加配置:
        spring.redis.host
        spring.redis.port等
    3.注入:
        @Autowired
        private RedisTemplate redisTemplate;
       操作: redisTemplate.opsForValue().get("");//操作string
                           opsForList().         //操作list
        等
    测试:redisTemplate.opsForValue().set("name1","springboottest");
    到redis服务器发现插入的key乱码 其实不是乱码 是因为RedisTemplate默认了使用jdk序列化 
    用代码获取都是正常的 只是用命令在服务器上看不太方便
    //4 5都是企业级开发需要的方式 4.配置一个自己的RedisTemplate配置类处理序列化问题 所有key采用string序列化 value采用json 具体详情看项目中的测试类RedisConfig 再测试: redisTemplate.opsForValue().set("name2","springboottest"); 到redis服务器发现插入的key是name2了 value是"springboottest" 5.使用原生redisTemplate的api不太方便 可以自己封装一个工具类 详细的看测试类中utils中的RedisUtil jedis采用直连 多线程不安全 还需使用jedis pool连接池 BIO模式 lettuce采用netty 实例多线程中共享 不存在线程不安全情况 可以不使用线程池减少线程数量 NIO模式

    12. redis.conf配置文件详解

    学习看redis.conf
    打开redis.conf
    1.# units are case insensitive so 1GB 1Gb 1gB are all the same.
    redis对大小写不敏感
    
    2.# include /path/to/local.conf
    # include /path/to/other.conf
    类似spring的import include 能包含其它的配置文件
    
    3.NETWORK
    bind //允许访问的ip
    protected-mode yes  //保护模式 默认开启 若关闭则允许所有外部访问 开启则允许bind的ip访问
    port    //端口设置
    
    4.GENERAL 通用配置
    daemonize yes    //守护进程 默认no yes允许退出继续在后台运行
    logfile /usr/local/bin/config/redislog.log    //日志文件路径
    databases 16    //数据库数量
    always-show-logo yes    //启动是否显示redis logo
    
    5.SNAPSHOTTING快照
    持久化 在规定时间内执行多少次操作能持久化到文件 .rdb .aof
    redis是内存数据库 没有持久化数据断电丢失
    
    save 900 1    //900秒内至少1个key修改 就进行持久化操作
    save 300 10
    save 60 10000
    
    stop-writes-on-bgsave-error no //若持久化失败是否停止工作
    rdbcompression yes    //是否压缩rdb文件 压缩会消耗cpu资源
    rdbchecksum yes    //保存rdb文件时是否校验
    dir ./                 //rdb文件保存目录
    
    
    6.REPLICATION 主从复制
    
    7.SECURITY 安全
    # requirepass foobared 登录redis密码 默认没有密码
    设置登录密码2种方式
    1.在配置文件加requirepass 1234
    2.redis-cli命令输入 config get requirepass    //查密码
                              config set requirepass "1234" //设置密码 
                              //设置密码后发现所有命令没权限了
                              auth 1234//登录
    
    8.CLIENTS 限制
    # maxclients 10000    //允许连接redis最大客户端的数量
    # maxmemory <bytes>    //redis配置最大内存容量
    # maxmemory-policy noeviction    //内存到上限处理策略
    
    9.APPEND ONLY MODE  aof模式
    appendonly no        //默认不开启aof模式(用rdb模式)
    appendfilename "appendonly.aof"    //aof持久化文件名称
    appendfsync everysec    //每秒同步一次(可能丢失1秒数据)
    # appendfsync always    //每次修改都同步(消耗性能)
    # appendfsync no        //不同步
        

    13.Redis持久化

    rdb:

    rdb保存的文件名是dump.rdb
    1.触发生成rdb备份文件的规则:
        1.配置文件中配置的规则满足触发 如save 900 1(900秒内有改过1次key)
        2.flushall
        3.shutdown退出redis时
    
    2.恢复rdb文件数据
    把rdb文件放到redis启动目录下自动恢复rdb中数据
    
    优点:
    1.适合大规模数据恢复
    2.对数据完整性要求不高
    
    缺点:
    1.需要一定的时间 若意外宕机 最后一次修改数据没有了
    2.子进程去生成rdb 会暂用一定的内存

    aof:

    aof保存的文件名是appendonly.aof
    aof将所有的命令都记录下来 可以看成记录命令的日志文件 恢复的时候将全部命令执行一遍重新构建
    redis.conf 中appendonly yes开启aof
    
    aof文件生成规则:
    # appendfsync always  //每次修改同步生成
    appendfsync everysec  //每秒同步生成
    # appendfsync no    //不生成
        
    注:若aof文件错误 redis启动会报错 
    修复aof文件方式:redis-check-aof --fix appendonly.aof
    
    优点:
    1.appendfsync always  //每次修改同步生成   数据完整性好
    appendfsync everysec  //每秒同步生成         数据完整性较好 但可能会丢失最后1秒数据
    
    缺点:
    1.aof远大于rdb 修复速度比rdb慢
    2.aof运行效率比rdb慢 
    扩展:
    1.redis只做缓存的话 不用弄持久化
    2.同时开启rdb和aof 优先载入aof 因为aof数据更完整

    14.redis发布订阅

    SUBSCRIBE runoobChat    //订阅
    PUBLISH runoobChat "Redis PUBLISH test"    //发布
    
    只能做一些简单的发布订阅
    复杂的用消息中间件mq做

    15.redis主从复制

    主从复制:将一台redis服务器的数据复制到其它redis服务器 主节点(master/leader) 从节点(slave/follower)
    数据只能由主节点到从节点 主节点写 从节点读(读写分离)
    80%的压力是读取 把读取的压力放到从节点
    
    主从复制主要作用
    1.数据冗余:主从复制实现了数据热备份 是持久化外的一种数据冗余方式
    2.故障恢复:主节点出问题 可以由从节点提供服务 以快速恢复。是一种服务冗余
    3.负载均衡:主从复制配合读写分离 主节点写入 从节点读取 写少读多的情况下分担负载 提高性能
    
    
    环境配置
    redis-cli查看主从复制的信息: info replication
    显示role就是这台redis是主机(master)或从机(slave)
    
    
    --------------------------------------------------------------------
    配置主从机方式(假设配置一主二从):
    1.配置主从机需要改的配置(redis.conf)(就是把主从机的配置信息和其它主从机区分开): //3个redis.conf都需要配置
    port         //redis端口区分开
    pidfile    //pid命名区分开
    logfile    //区分log命名
    dbfilename    //rdb文件命名区分
    2.配置好后3台默认都是主机 那么选2台当从机 从机需要选定一台当它的主机 //重点
    在从机中的redis-cli中输入slaveof 127.0.0.1 6379 //即让自己由主机变从机 它主机的地址是127.0.0.1 6379
    slaveof no one  //本机作为从机失效 恢复为主机
    3.步骤2是通过命令配置主从 不是永久的
    在redis.conf中配置
    # replicaof <masterip> <masterport>
    写入对应的ip 端口就好了
    如果主机有密码则在下面配置
    # masterauth <master-password>
    
    注:1.主机只负责写 从机只负责读
        2.主机写入的从机都会同步数据
        3.主从复制虽然用slaveof命令的方式每次重启都需要重新配置 但还是比
        在配置文件中配置更好一点 因为若出现某一台宕机 可以用命令快速的
       切换主从 

    16.哨兵模式

    主从模式中如果主机宕机 得手动切换主从(把其中一台从机换成主机) 人工处理耗时  所以优先考虑哨兵模式
    哨兵是一个独立的进程 其原理是哨兵发送命令监控多个redis实例 监控是否宕机
    redis-sentinel
    一个哨兵可能有问题 可以用多个哨兵对多个redis服务监控 哨兵间也互相监控
    (用哨兵模式建议6个服务器 1主2从3哨兵)
    
    配置哨兵方式:
    1.建一个哨兵配置文件sentinel.conf
    #sentinel monitor 被监控名称 host ip 1//1是多少个哨兵认为主机宕机时开始投票选一台从机当主机 host ip是主节点的redis
    sentinel monitor myredis 127.0.0.1 6379 1
    2.启动哨兵
    redis-sentinel sentinel.conf
    
    
    再次梳理流程:
    新建哨兵配置文件 配置哨兵监听的主节点主机 主节点宕机后被至少1个哨兵监听到时进行投票(被多少个哨兵监听到宕机是上述配置文件中定义的) 投票算法会选择一台从节点作为新的主节点 若宕机的那台主机恢复了 哨兵会自动把宕机的主机变更为从机
    
    
    优点:
    1.哨兵基于主从复制 所有主从复制的优点都有
    2.故障可以转移 高可用性
    3.哨兵模式就是主从复制的升级版 手动到自动
    
    缺点:
    1.不容易在线扩容 
    2.哨兵模式全局配置内容比较多

    17.redis缓存穿透和雪崩

    缓存穿透(查不到导致):用户查一个数据 缓存没有导致查数据库 数据库也没有导致重复查询
    查询很多时导致给数据库造成很大压力 这就是缓存穿透
    解决方式:
    1.数据库没有的数据redis缓存设空对象 减轻数据库压力
    2.布隆过滤器
    //布隆过滤器是一个数据结构 对所有可能的查询的参数以hash存储 在控制层进行校验 不符的丢弃以缓解redis及数据库的压力
    
    
    缓存击穿(查量太大缓存过期导致):是比缓存穿透更严重一级 一个热词用户搜索量非常大 但redis的key过期 就在过期的这一瞬间高并发都到数据库 服务器这一瞬间没抗住
    解决方式:
    1.key设不过期
    2.分布式锁 每个key只用一个线程去查询数据库 其余的等待
    
    
    
    缓存雪崩:某一段时间 缓存集体失效或redis宕机
    解决方式:
    1.停掉一些服务保证主要服务可用 如双11退单服务停用
    2.数据预热 预先将可能大部分访问的数据访问一遍加载到缓存中
    3.redis高可用 就是多设几台redis
    4.限流降级 缓存失效的话通过加锁或队列控制读写访问数据库的线程 如对某一key只允许一个线程查询
  • 相关阅读:
    Graph 学习
    忘记 mysql 8.0 root 密码 怎么修改
    HTML字符实体(关于&nbsp;&gt;&lt;等)
    Sqlserver 中系统表sysobjects、syscolumns以及函数object_id
    SQL Server创建索引(转)
    改善SQL语句(转)
    (转)SqlServer索引及优化详解(1)
    标签点击不返回顶部和不刷新页面方法
    c#模拟js escape方法
    获取枚举描述信息
  • 原文地址:https://www.cnblogs.com/hbhb/p/14280213.html
Copyright © 2020-2023  润新知