zoukankan      html  css  js  c++  java
  • 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毫秒,取
    决于构建缓存的速度)后,重新执行函数,直到获取到数据。
  • 相关阅读:
    Python中的类(上)
    Django REST Framework API Guide 07
    Django REST Framework API Guide 06
    Django REST Framework API Guide 05
    Django REST Framework API Guide 04
    Django REST Framework API Guide 03
    Django REST Framework API Guide 02
    Django REST Framework API Guide 01
    Django 详解 信号Signal
    Django 详解 中间件Middleware
  • 原文地址:https://www.cnblogs.com/linhongwenBlog/p/12201063.html
Copyright © 2011-2022 走看看