• redis的使用小记


    常用帮助地址

    www.redisdoc.com
    http://www.redis.cn/


    Redis = remote dictionary server
    redis是单线程模式的 一次只能处理一个请求,且区分大小写。

    但redis的速度挺快的,主要原因是

    1.redis是单线程模式的
    2.redis的数据放在内存中
    3.linux的机制多路复用IO


    包含了以下几种数据格式:String、Map、list、set、有序集合 sorted sets


    登录: ./redis-cli -h ip -p port

    redis的命令

    ping 正常时返回pong 查看当前redis是否正常
    dbsize 查看当前库的key数量
    select db 切换数据库,切换到第一个库
    flushdb 删除当前库的所有数据

    操作key、String、Hash、List、Set、Zset

    操作key的命令

    keys * 显示当前库所有key(生产不要用),可以使用通配符 ?一个字符 *-多个字符
    exists key1 key2 是否存在当前key 返回数量
    expire key seconds   设置已存在的key的生存时间,单位S。设置成功返回1,失败返回0
    pexpire key milliseconds 设置已存在的key的生存时间,单位毫秒
    expireat key timestamp 设置key在某一个时间戳时过期
    persist key 设置某个key永远不会过期
    ttl 返回key剩余的生存时间 -1永久 -2不存在
    type 查看key对应的值是什么类型的
    del key1 key2 从当前库中删除一个或者多个key,返回删除的数量
    rename key newkey 键重命名。如果新键已经存在,则会被覆盖
    renamenx key newkey 建重命名。新建不存在才可以重命名

    key在redis实例之内迁移

    move key db

    key在两个不同redis的迁移

    单key迁移

    dump key  --在源redis上将这个键值序列化转为RDB存储。

    restore key ttl value --在目标redis上。restore将上面序列化的值进行复原。ttl代表过期时间,ttl=0代表不会过期

    下面用一个
    例子演示完整过程。
    1)在源Redis上执行dump:
    redis-source> set hello world
    OK
    redis-source> dump hello
    "x00x05worldx06x00x8f<Tx04%xfcNQ"
    2)在目标Redis上执行restore:
    redis-target> get hello
    (nil)
    redis-target> restore hello 0 "x00x05worldx06x00x8f<Tx04%xfcNQ"
    OK
    redis-target> get hello
    "world"

     多个key迁移

     migrate host port key|"" destination-db timeout [copy] [replace] [keys key [key]]

    下面对migrate的参数进行逐个说明:
    ·host:目标Redis的IP地址。
    ·port:目标Redis的端口。
    ·key|"":在Redis3.0.6版本之前,migrate只支持迁移一个键,所以此处是要迁移的键,但Redis3.0.6版本之后支持迁移多个键,如果当前需要迁移多个键,此处为空字符串""。
    ·destination-db:目标Redis的数据库索引,例如要迁移到0号数据库,这
    里就写0。
    ·timeout:迁移的超时时间(单位为毫秒)。
    ·[copy]:如果添加此选项,迁移后并不删除源键。
    ·[replace]:如果添加此选项,migrate不管目标Redis是否存在该键都会
    正常迁移进行数据覆盖。
    ·[keys key[key...]]:迁移多个键,例如要迁移key1、key2、key3,此处填
    写“keys key1 key2 key3”。
    migrate 127.0.0.1 6380 hello 0 1000 replace

     redis可以操作多种类型的数据,下面对类型数据操作进行描述

     使用redis存储数据的时候,有时候为了查看的方便,通常会有层级或者说是目录,这时候我们在set的时候,需要将key值使用“:”的符号来区分层级关系

    比如:set(“a:b”, “123”),那么在redis中就是a目录下的key值为b的value为123。

    操作String型数据

    set key value 设置值,已存在的覆盖掉

    set的几个选项
     ex seconds : 为键设置秒级过期时间
     px milliseseconds : 为键设置毫秒级过期时间
     nx 键必须不存在,才可以设置成功。用于添加
     xx 与nx相反,键必须存在,才可以设置成功。用于更新

    get key 获取指定key的值,nil没有值

    incr key 把key的值+1。对整数值进行计算,否则报错;若key不存在,初始化为0 再加1
    decr key 把key的值-1。对整数值进行计算,否则报错;若key不存在,初始化为0 再减1
    append key value 把value追加到key后。返回追加后的长度;若key不存在,等同于set命令
    strlen key 求长度,没有key返回0
    getrange key start end 求子段,类似subString.最左边是0,最右边是-1
    setrange key offset value 用value覆盖offset开始的内容
    mset 一次性设置多对K-V
    mget 一次性获取多对K对应的值

    操作Hash型数据-用来存java对象

    hset key field value 将key中的field字段的值设为value。如果key不存在,则新建hash表,执行赋值。如果field存在,则覆盖值
    返回值:如果field是hash中新field。且设置成功,返回1
    如果field已经存在,旧值覆盖新值,返回0
    hget key field 获取哈希表key中field的值
    hmset key field value [field value] 一次性设置多个值
    hmget key field [field] 一次性获取多个值
    hgetall key 获取key中所有的字段和值
    hdel key field [field] 删除多个field字段。返回删除field的数量
    hkeys key 获取key中所有的field
    hvals key 获取key中所有的值
    hexists key field 查看哈希表key中。field是否存在、存在1,不存在0

    操作List型数据

    lpush key value[value] 将一个或者多个值添加到列表key的表头(最左边)
    rpush key value[value] 将一个或者多个值添加到列表key的表尾(最右边)
    lrange key start stop 获取key中指定区间内的元素
    lindex key index 获取下标的值
    llen key 求key成员的个数
    lrem key count value 删掉重复的几个数据。count=0 代表全删
    lset key index value 将key下标为index的元素值设置为value
    linsert key BEFORE|AFTER pivot value 将value插入到key中位于值pivot之前或者之后的位置
    lpop 从列表最左侧取出数据,并删掉
    rpop 从列表最右侧取出数据,并删掉

    操作set集合数据-无序、不可重复

    sadd key member [member] 将一个或者多个member加入到集合key中。已经存在的member将会被忽略,不会再加入
    smembers key 获取key里面所有的成员
    sismember key member 判断member元素是否是集客key的成员 1-存在 0-不存在
    scard key 获取集合里面的元素个数
    srem key member [member] 删除集合key中的一个或者多个member元素
    srandmember key [count] 随机返回集合中count个元素,但是并没有删除,元素依然在集合中。count为负数,取出的值可能是重复的
    spop key [count] 随机从集合中删除count个元素
    sinter key1 key2 取两个集客的交集
    sunion key1 key2 取两个集客的并集

    操作zset有序集合数据-有序、不重复的。

    通过分数来为集合中的成员进行排序。同分数通过字典顺序排序
    zadd key score member [score member] 将一个或者多个member元素和score元素 加入到有序集合key中。如果member已经存在,则更新值。score可以是整数或者浮点数
    zrange key start stop [withscores] 查询有序集合指定区间内的元素。withscores会将参数一并返回
    zrevrange key start stop [withscores] 用法同zrange。只是显示顺序反过来,按照score从大到小
    zrem key member [member] 删除集合中key中 一个或者多个成员
    zcard key 获取有序集合key中的元素成员个数
    zrangebyscore key min max [withscores] [LIMIT offset count] 获取有序集合中,所有score值介于min和max之间(包括min和max)的成员。LIMIT是分页。offset
    如果使用 (min (max 则代表--不包括min和max的成员
    -inf集合中的最小值
    +inf集合中的最大值
    zrevrangebyscore key max min [withscores] [LIMIT offset count] 用法类似zrangebyscore。注意max和min的位置,显示顺序反过来,按照score从大到小
    zcount key min max 统计key中score值在min和max之间的成员数量

    事务

    保证几个redis命令执行时中间不会被其他任何操作打断。

    multi 标志事务开始
    exec 标志事务的提交。如果执行exec之前 某个命令是错的,那么整个事务都会被取消。如果执行exec之后 某个命令失败,其他命令会继续执行
    discard 标志取消事务
    watch key [key] 监视一个或者多个key,如果在事务执行前这个key被其他命令所改动,那么事务将被打断
    unwatch 取消所有的watch命令

    持久化:优先使用aof。

    RDB机制。将内存的数据写入到磁盘的二进制文件中,重启时从rdb文件读取。N秒内数据集至少有M个key改动。通过配置redis.conf文件实现。不能100%保存数据
    redis.conf需要的配置项
    a.save <seconds> <changes>
    b.dbfilename 设置RDB文件名称,默认是dump.rdb
    c.dir指定RDB文件的存储位置,默认是./当前目录

    AOF方式。redis每次接收到一条可以改变数据的命令时,就把该命令写入一个AOF文件中。当redis重启时,通过AOF文件恢复.通过配置redis.conf文件实现
    redis.conf需要的配置项
    a.appendonly 默认是no,改成yes开启aof持久化
    b.appendfilename 指定aof文件名,默认文件名是appendonly.aof
    c.dir 指定RDB和AOF文件存放的目录,默认是./
    d.appendfsync 配置向aof文件写命令数据的策略

    1. no 不主动进行同步操作,而是交给操作系统来做(30S一次),比较快但是不是很安全
    2. always 每次执行写入都会执行同步,慢一些但是比较安全
    3. everysec 每秒执行一次同步操作,比较平衡。默认项

    e.auto-aof-rewrite-min-size 允许重写最小aof文件大小。默认是64M.当aof文件大于64M时。开始整理aof,去掉无用的操作命令,缩小aof文件

    主从复制 master/slave。一般在从上进行持久化
    主redis用来写。从redis用来读,从不能写
    主从复制例子6380为主 6382和6384为从
    1.编辑主6380.conf。在空文件加入如下内容
    include /usr/local/redis-4.0.13/redis.conf --引入原本的配置文件
    daemonize yes --后台启动应用。相当于./redis-server &
    port 6380
    pidfile /var/run/redis_6380.pid --自定义文件,表示当前程序的pid,进程id
    logfile 6380.log
    dbfilename dump6380.rdb --持久化文件名称
    2.编辑从6382.conf。在空文件加入如下内容
    include /usr/local/redis-4.0.13/redis.conf --引入原本的配置文件
    daemonize yes --后台启动应用。相当于./redis-server &
    port 6382
    pidfile /var/run/redis_6382.pid --自定义文件,表示当前程序的pid,进程id
    logfile 6382.log
    dbfilename dump6382.rdb --持久化文件名称
    slaveof 127.0.0.1 6380
    3.编辑从6384.conf。在空文件加入如下内容
    include /usr/local/redis-4.0.13/redis.conf --引入原本的配置文件
    daemonize yes --后台启动应用。相当于./redis-server &
    port 6384
    pidfile /var/run/redis_6384.pid --自定义文件,表示当前程序的pid,进程id
    logfile 6384.log
    dbfilename dump6384.rdb --持久化文件名称
    slaveof 127.0.0.1 6380
    启动3个redis主从节点。分别登录3个redis后 用info replication查看信息

    容灾

    手动容灾处理

    1.在要升级为主的机器上执行 slaveof no one 将一台slave服务器提升为master
    2.在其他备份从节点上执行 slaveof 127.0.0.1 6382 将slave挂到新的master上

    哨兵:自动容灾

    监控:Sentiel不断监控主服务和从服务是否按照预期正常工作
    提醒:被监控的redis出现问题时,sentinel会通知管理员或者其他应用程序
    自动故障转移:监控的主redis不能正常工作,sentinel会开始进行故障迁移操作。将某一个从升级为主。让其他从挂到新的主服务器。同时向客户端提供新的主服务器地址
    sentinel monitor 全部监控master节点

    集群的容灾

    redis3.0后支持集群部署。集群一般需要6个节点,使用ruby进行整个集群的关联。为3主3从,主从之间和进行复制。

    如果集群的某个分槽的主从都挂了,分槽不可用,认定这个集群不可用

    如果集群超过一半的主节点都挂了,也认定这个集群不可用

    设置密码

    设置密码 修改redis.conf 中的requirepass

    Jedis+commons-Pool

    每秒输出一次redis的内存使用量

    redis-cli -r 100 -i 1 info | grep used_memory_human

    redis发布订阅模式

    发布消息

    publish channel message

    订阅消息

    subscribe channel [channel]

    一些优化方案

    缓存更新优化----合理安排缓存清除时间。

    缓存粒度控制----合理存储字段,不将整个表的字段都存下来,只存热点字段,节省内存和反编译时间

    穿透优化----恶意攻击或者爬虫时,大量数据redis中没有,直接到存储层进行查询,存储层也没有,导致redis缓存大量的空对象。

    解决办法:

    1.将空对象设置较短的过期时间(不超过5分钟)

    2.布隆拦截器。将常用数据都缓存到redis中。拦截器发现redis中没有,也认定存储层没有。不去访问存储层。

    无底洞优化----横向增加redis节点的时候,获取数据需要消耗大量的网络时间,达不到优化目的

    雪崩优化----redis服务不可用 或者大量key同时到期,大量的数据请求直达存储层。造成存储层优化

    解决办法:

    1.保证缓存层服务高可用

    2.不同的key,设置不同的过期时间,具体值可以根据业务决定,让缓存失效的时间点尽量均匀

    3.使用Hystrix组件为后端限流并降级

    热点key重建优化----一个热点key失效后,大量的访问使得多个线程同时开始对该热点key进行缓存,造成死锁

    解决办法:

    1.设置数据永不过期

    2.互斥锁。只允许一个现场进行缓存重建。其他线程等待重建完成后,重新获取数据。

    String get(String key) {
     // 从Redis中获取数据
     String value = redis.get(key);
     // 如果value为空,则开始重构缓存
     if (value == null) {
     // 只允许一个线程重构缓存,使用nx,并设置过期时间ex
     String mutexKey = "mutext:key:" + key;
     if (redis.set(mutexKey, "1", "ex 180", "nx")) {
     // 从数据源获取数据
     value = db.get(key);
     // 回写Redis,并设置过期时间
     redis.setex(key, timeout, value);
     // 删除key_mutex
     redis.delete(mutexKey);
     } 
     // 其他线程休息50毫秒后重试
     else {
     Thread.sleep(50);
     get(key);
     }
     }
     return value;
    }
    1)从Redis获取数据,如果值不为空,则直接返回值;否则执行下面的
    2.1)和2.2)步骤。
    2.1)如果set(nx和ex)结果为true,说明此时没有其他线程重建缓存,
    那么当前线程执行缓存构建逻辑。
    2.2)如果set(nx和ex)结果为false,说明此时已经有其他线程正在执
    行构建缓存的工作,那么当前线程将休息指定时间(例如这里是50毫秒,取
    决于构建缓存的速度)后,重新执行函数,直到获取到数据。
  • 相关阅读:
    若依项目上传下载附件实现
    若依项目实现导入功能
    若依项目开发实践
    若依项目人员选择器实现
    springboot打成Jar包后部署至Linux服务器上
    linux下启动tomcat----Cannot find ./catalina.sh
    Linux下更换jdk和配置环境变量
    若依项目分模块集成uflo2
    若依项目模块化开发
    Java中涉及到金额业务的处理
  • 原文地址:https://www.cnblogs.com/linhongwenBlog/p/12201063.html
Copyright © 2020-2023  润新知