美文网首页
Redis(一)之入门详解

Redis(一)之入门详解

作者: frederickhou | 来源:发表于2019-08-09 17:24 被阅读0次

    Redis简介:

    Redis是一款开源的、高性能的键-值存储(key-value store)。它常被称作是一款数据结构服务器(data structure server)。

    Redis的键值可以包括字符串(strings)类型,同时它还包括哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等数据类型。 对于这些数据类型,你可以执行原子操作。例如:对字符串进行附加操作(append);递增哈希中的值;向列表中增加元素;计算集合的交集、并集与差集等。

    为了获得优异的性能,Redis采用了内存中(in-memory)数据集(dataset)的方式。同时,Redis支持数据的持久化,你可以每隔一段时间将数据集转存到磁盘上(snapshot),或者在日志尾部追加每一条操作命令(append only file,aof)。

    Redis同样支持主从复制(master-slave replication),并且具有非常快速的非阻塞首次同步( non-blocking first synchronization)、网络断开自动重连等功能。同时Redis还具有其它一些特性,其中包括简单的事物支持、发布订阅 ( pub/sub)、管道(pipeline)和虚拟内存(vm)等 。
    Redis具有丰富的客户端,支持现阶段流行的大多数编程语言

    Redis安装:

    下载最新稳定版 redis( http://redis.io/download )
    tar zxvf redis-5.0.4.tar.gz 解压后的目录如下:

    ls
    00-RELEASENOTES  COPYING  Makefile   redis.conf       runtest-sentinel  tests
    BUGS             deps     MANIFESTO  runtest          sentinel.conf     utils
    CONTRIBUTING     INSTALL  README.md  runtest-cluster  src
    
    

    cd src 进入src目录
    make 编译Redis
    make test 可以测试一下,最终成功测试结果如下。

    \o/ All tests passed without errors!
    

    make install 安装

    Hint: It's a good idea to run 'make test' ;)
    
        INSTALL install
        INSTALL install
        INSTALL install
        INSTALL install
        INSTALL install
    

    启动Redis服务端如下(默认端口号6379):
    此时redis已经运行,但要获得好的性能和符合项目特点,还需要对配置文件进行合理的配置,对/etc/redis/redis.conf文件进行修改即可。

    redis-server 
    16923:C 27 Apr 21:57:47.289 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
    16923:M 27 Apr 21:57:47.290 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                    _._                                                  
               _.-``__ ''-._                                             
          _.-``    `.  `_.  ''-._           Redis 3.0.6 (00000000/0) 64 bit
      .-`` .-```.  ```\/    _.,_ ''-._                                   
     (    '      ,       .-`  | `,    )     Running in standalone mode
     |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
     |    `-._   `._    /     _.-'    |     PID: 16923
      `-._    `-._  `-./  _.-'    _.-'                                   
     |`-._`-._    `-.__.-'    _.-'_.-'|                                  
     |    `-._`-._        _.-'_.-'    |           http://redis.io        
      `-._    `-._`-.__.-'_.-'    _.-'                                   
     |`-._`-._    `-.__.-'    _.-'_.-'|                                  
     |    `-._`-._        _.-'_.-'    |                                  
      `-._    `-._`-.__.-'_.-'    _.-'                                   
          `-._    `-.__.-'    _.-'                                       
              `-._        _.-'                                           
                  `-.__.-'                                               
    

    连接客户端如下

    redis-cli -h 127.0.0.1 -p 6379
    127.0.0.1:6379> 
    

    Redis的数据类型:

    Keys 非二进制安全的字符类型( not binary-safe strings )

    Values Strings Lists Sets Sorted sets Hash

    String类型

    string是redis最基本的类型,而且string类型是二进制安全的。
    redis的string可以包含任何数据。包括jpg图片或者序列化的对象。
    最大上限是1G字节。
    如果只用string类型,redis就可以被看作加上持久化特性的memcached

    String相关命令

    set key value 设置key对应的值为string类型的value,返回1表示成功,0失败

    setnx key value 同上,如果key已经存在,返回0 。nx 是not exist的意思

    get key 获取key对应的string值,如果key不存在返回nil

    getset key value 设置key的值,并返回key的旧值。如果key不存在返回nil

    mget key1 key2 ... keyN 一次获取多个key的值,如果对应key不存在,则对应返回nil。下面是个实验, nonexisting不存在,对应返回nil

    127.0.0.1:6379> set newKey abd
    OK
    127.0.0.1:6379> setnx newKey abd
    (integer) 0
    127.0.0.1:6379> get newKey
    "abd"
    127.0.0.1:6379> mget myKey newKey otherkey
    1) "abc"
    2) "abd"
    3) (nil)
    

    List类型:
    redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素。这使得list既可以用作栈,也可以用作队列。
    list的pop操作还有阻塞版本的。当我们[lr]pop一个list对象时,如果list是空,或者不存在,会立即返回nil。但是阻塞版本的b[lr]pop则可以阻塞,当然可以加超时时间,超时后也会返回nil。为什么要阻塞版本的pop呢,主要是为了避免轮询。举个简单的例子如果我们用list来实现一个工作队列。执行任务的thread可以调用阻塞版本的pop去获取任务这样就可以避免轮询去检查是否有任务存在。当任务来时候工作线程可以立即返回,也可以避免轮询带来的延迟。

    List的相关命令:

    lpush key string 在key对应list的头部添加字符串元素,返回1表示成功,0表示key存在且不是list类型。

    rpush key string 同上,在尾部添加。

    llen key 返回key对应list的长度,key不存在返回0,如果key对应类型不是list返回错误。

    lrange key start end 返回指定区间内的元素,下标从0开始,负值表示从后面计算,-1表示倒数第一个元素 ,key不存在返回空列表。

    ltrim key start end 截取list,保留指定区间内元素,成功返回1,key不存在返回错误。

    lset key index value 设置list中指定下标的元素值,成功返回1,key或者下标不存在返回错误。

    lrem key count value 从key对应list中删除count个和value相同的元素。count为0时候删除全部。

    lpop key 从list的头部删除元素,并返回删除元素。如果key对应list不存在或者是空返回nil,如果key对应值不是list返回错误。

    rpop 同上,但是从尾部删除。

    blpop key1...keyN timeout 从左到右扫描返回对第一个非空list进行lpop操作并返回,比如blpop list1 list2 list3 0 ,如果list不存在,list2,list3都是非空则对list2做lpop并返回从list2中删除的元素。如果所有的list都是空或不存在,则会阻塞timeout秒,timeout为0表示一直阻塞。当阻塞时,如果有client对key1...keyN中的任意key进行push操作,则第一在这个key上被阻塞的client会立即返回。如果超时发生,则返回nil。

    brpop 同blpop,一个是从头部删除一个是从尾部删除。

    rpoplpush srckey destkey 从srckey对应list的尾部移除元素并添加到destkey对应list的头部,最后返回被移除的元素值,整个操作是原子的.如果srckey是空或者不存在返回nil。

    127.0.0.1:6379> lpush myList a
    (integer) 1
    127.0.0.1:6379> llen myList
    (integer) 1
    127.0.0.1:6379> lrange myList 0 -1
    1) "b"
    2) "a"
    127.0.0.1:6379> ltrim myList 0 1
    OK
    127.0.0.1:6379> lset myList 0 www
    OK
    127.0.0.1:6379> lrem myList 3 b
    (integer) 3
    

    Set类型:

    redis的set是string类型的无序集合。
    set元素最大可以包含(2的32次方-1)个元素。
    set的是通过hash table实现的,hash table会随着添加或者删除自动的调整大小
    关于set集合类型除了基本的添加删除操作,其他有用的操作还包含集合的取并集(union),交集(intersection),差集(difference)。通过这些操作可以很容易的实现sns中的好友推荐和blog的tag功能。

    Set的相关命令:

    sadd key member 添加一个string元素到,key对应的set集合中,成功返回1,如果元素以及在集合中返回0,key对应的set不存在返回错误。

    srem key member 从key对应set中移除给定元素,成功返回1,如果member在集合中不存在或者key不存在返回0,如果key对应的不是set类型的值返回错误。

    spop key 删除并返回key对应set中随机的一个元素,如果set是空或者key不存在返回nil
    srandmember key 同spop,随机取set中的一个元素,但是不删除元素。

    smove srckey dstkey member 从srckey对应set中移除member并添加到dstkey对应set中,整个操作是原子的。成功返回1,如果member在srckey中不存在返回0,如果key不是set类型返回错误。

    scard key 返回set的元素个数,如果set是空或者key不存在返回0。

    sismember key member 判断member是否在set中,存在返回1,0表示不存在或者key不存在。

    sinter key1 key2...keyN 返回所有给定key的交集。

    sinterstore dstkey key1...keyN 同sinter,但是会同时将交集存到dstkey下。

    sunion key1 key2...keyN 返回所有给定key的并集。

    sunionstore dstkey key1...keyN 同sunion,并同时保存并集到dstkey下。

    sdiff key1 key2...keyN 返回所有给定key的差集。

    sdiffstore dstkey key1...keyN 同sdiff,并同时保存差集到dstkey下。

    smembers key 返回key对应set的所有元素,结果是无序的。

    127.0.0.1:6379> sadd newKey hello
    (integer) 1
    127.0.0.1:6379> sadd newKey work
    (integer) 1
    127.0.0.1:6379> sadd newKey word
    (integer) 1
    127.0.0.1:6379> spop newKey
    "work"
    127.0.0.1:6379> srandmember newKey
    "hello"
    127.0.0.1:6379> sadd myKey hello
    (integer) 1
    127.0.0.1:6379> smove newKey myKey word
    (integer) 1
    127.0.0.1:6379> scard newKey
    (integer) 1
    127.0.0.1:6379> scard myKey
    (integer) 2
    127.0.0.1:6379> sismember myKey hello 
    (integer) 1
    127.0.0.1:6379> sinter newKey myKey
    1) "hello"
    127.0.0.1:6379> sunion newKey myKey
    1) "hello"
    2) "word"
    127.0.0.1:6379> sunionstore dstkey newKey myKey
    (integer) 2
    127.0.0.1:6379> sdiff newKey myKey
    (empty list or set)
    

    Sorted Set类型:

    和set一样sorted set也是string类型元素的集合,不同的是每个元素都会关联一个double类型的score。sorted set的实现是skip list和hash table的混合体。当元素被添加到集合中时,一个元素到score的映射被添加到hash table中,另一个score到元素的映射被添加到skip list并按照score排序,所以就可以有序的获取集合中的元素。

    Sorted Set的相关命令:

    zadd key score member 添加元素到集合,元素在集合中存在则更新对应score。

    zrem key member 删除指定元素,1表示成功,如果元素不存在返回0。

    zincrby key incr member 增加对应member的score值,然后移动元素并保持skip list有序。返回更新后的score值。

    zrank key member 返回指定元素在集合中的排名(下标,非score),集合中元素是按score从小到大排序的。

    zrevrank key member 同上,但是集合中元素是按score从大到小排序。

    zrange key start end 类似lrange操作从集合中取指定区间的元素。返回的是有序结果。

    zrevrange key start end 同上,返回结果是按score逆序的。

    zrangebyscore key min max 返回集合中score在给定区间的元素。

    zcount key min max 返回集合中score在给定区间的数量。

    zcard key 返回集合中元素个数。

    zscore key element 返回给定元素对应的score。

    zremrangebyrank key min max 删除集合中排名在给定区间的元素。

    zremrangebyscore key min max 删除集合中score在给定区间的元素。

    Hash类型:

    redis hash是一个string类型的field和value的映射表。
    hash特别适合用于存储对象。相较于将对象的每个字段存成单个string类型。将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。

    Hash的相关命令:

    hset key field value 设置hash field为指定值,如果key不存在,则先创建。

    hget key field 获取指定的hash field。

    hmget key filed1....fieldN 获取全部指定的hash filed。

    hmset key filed1 value1 ... filedN valueN 同时设置hash的多个field。

    hincrby key field integer。

    key的相关命令

    set key value 设置一个新的数据,如果key不存在则创建,如果存在则更新key对应value的值。

    GET key 获取key对应value的值,如果存在则返回,不存在返回nil。

    exits key 测试指定key是否存在,返回1表示存在,0不存在。

    del key1 key2 ....keyN 删除给定key,返回删除key的数目,0表示给定key都不存在。

    type key 返回给定key的value类型。返回 none 表示不存在,key有string字符类型,list 链表类型 set无序集合类型等...

    keys pattern 返回匹配指定模式的所有key(支持*,?,[abc ])的方式。

    RANDOMKEY 返回从当前数据库中随机选择的一个key,如果当前数据库是空的,返回空串。

    RENAME oldkey newkey 原子的重命名一个key,如果newkey存在,将会被覆盖,返回1表示成功,0失败。失败可能是oldkey不存在或者和newkey相同。

    RENAMENX oldkey newkey 同上,但是如果newkey存在返回失败。

    DBSIZE 返回当前数据库的key数量。

    EXPIRE key seconds 为key指定过期时间,单位是秒。返回1成功,0表示key已经设置过过期时间或者不存在。

    ttl key 返回设置了过期时间的key的剩余过期秒数, -2表示key不存在或者没有设置过过期时间。

    SELECT db-index 通过索引选择数据库,默认连接的数据库索引是0,默认数据库数是16个。返回1表示成功,0失败。

    MOVE key db-index 将key从当前数据库移动到指定数据库。返回1成功。0 如果key不存在,或者已经在指定数据库中。

    FLUSHDB 删除当前数据库中所有key,此方法不会失败。慎用。

    FLUSHALL 删除所有数据库中的所有key,此方法不会失败。更加慎用。

    示例如下:

    127.0.0.1:6379> set newKey abc
    OK
    127.0.0.1:6379> EXISTS newKey
    (integer) 1
    127.0.0.1:6379> type newKey
    string
    127.0.0.1:6379> KEYS new*
    1) "newKey"
    127.0.0.1:6379> del newKey
    (integer) 1
    127.0.0.1:6379> RANDOMKEY
    (nil)
    127.0.0.1:6379> RENAME newKey myKey
    OK
    127.0.0.1:6379> DBSIZE
    (integer) 1
    127.0.0.1:6379> EXPIRE myKey 10
    (integer) 1
    127.0.0.1:6379> ttl myKey
    (integer) 5
    127.0.0.1:6379> FLUSHDB
    OK
    127.0.0.1:6379> FLUSHALL
    OK
    

    Redis功能:

    持久化:

    redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化,这是相对memcache来说的一个大的优势。redis支持两种持久化方式,一种是 Snapshotting(快照)也是默认方式,另一种是Append-only file(缩写aof)的方式。

    • Snapshotting

    快照是默认的持久化方式。这种方式将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以配置自动做快照持久 化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置。
    save 900 1 #900秒内如果超过1个key被修改,则发起快照保存�
    save 300 10 #300秒内容如超过10个key被修改,则发起快照保存

    • Append-only file

    aof比快照方式有更好的持久化性,是由于在使用aof持久化方式时,redis会将每一个收到的写命令都通过write函数追加到文件中(默认是 appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于os会在内核中缓存 write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。不过我们可以通过配置文件告诉redis我们想要 通过fsync函数强制os写入到磁盘的时机。

    有三种方式如下(默认是:每秒fsync一次)

    appendonly yes //启用aof持久化方式

    appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用

    appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐

    appendfsync no //完全依赖os,性能最好,持久化没保证

    主从复制:

    主从复制允许多个slave server拥有和master server相同的数据库副本。下面是关于redis主从复制的一些特点

    • 1.master可以有多个slave
    • 2.除了多个slave连到相同的master外,slave也可以连接其他slave形成图状结构
    • 3.主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理client发来的请求。相反slave在初次同步数据时则会阻塞,不能处理client的请求。
    • 4.主从复制可以用来提高系统的可伸缩性(我们可以用多个slave 专门用于client的读请求,比如sort操作可以使用slave来处理),也可以用来做简单的数据冗余。
    • 5.可以在master禁用数据持久化,只需要注释掉master 配置文件中的所有save配置,然后只在slave上配置数据持久化。

    事务:

    redis对事务的支持目前还比较简单。redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。
    Multi 事物开始
    Exec 执行事务
    Discard 放弃事物
    Watch 监听key
    Unwatch 放弃所有key的监听
    watch 命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。注意watch的key是对整个连接有效的,和事务一样,如果连接断开,监视和事务都会被自动清除

    发布订阅:

    发布订阅(pub/sub)是一种消息通信模式。订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型,redis将消息类型称为通道(channel)。当发布者通过publish命令向redis server发送特定类型的消息时。订阅该消息类型的全部client都会收到此消息。这里消息的传递是多对多的。一个client可以订阅多个 channel,也可以向多个channel发送消息。�
    Subscribe
    Unsubscribe
    Psubscribe
    Punsubscribe
    Publish

    管道:

    redis是一个cs模式的tcp server,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常 会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client。

    虚拟内存:

    redis没有使用os提供的虚拟内存机制而是自己实现了自己的虚拟内存机制 ,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出内存空间用于其他需要访问的数据。尤其是对于redis这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个redis server外。另外的能够提高数据库容量的办法就是使用vm把那些不经常访问的数据交换的磁盘上。如果我们的存储的数据总是有少部分数据被经常访问,大 部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃。当少量数据被经常访问时,使用vm不但能提高单台redis server数据库的容量,而且也不会对性能造成太多影响。
    vm-enabled yes #开启vm功能
    vm-swap-file /tmp/redis.swap #交换的value保存的文件路径/tmp/redis.swap
    vm-max-memory 1000000 #最大内存上限,超过后开始交换value到磁盘文件
    vm-page-size 32 #每个页面的大小32个字节
    vm-pages 134217728 #最多使用在文件中使用多少页面
    vm-max-threads 4 #用于执行value对象换入换出的工作线程数量,0表示不使用工作线程

    Redis应用场景:

    • 1.排行榜应用,取TOP N操作

    这个是以某个条件为权重,比如按顶的次数排序,这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score,将具体的数据设置成相应的value,每次只需要执行一条ZADD命令即可。

    • 2.需要精准设定过期时间的应用

    比如你可以把上面说到的sorted set的score值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序,定时清除过期数据了,不仅是清除Redis中的过期数据,你完全可以把Redis里这个过期时间当成是对数据库中数据的索引,用Redis来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录。

    • 3.计数器应用

    Redis的命令都是原子性的,你可以轻松地利用INCR,DECR命令来构建计数器系统。

    • 5.Uniq操作,获取某段时间所有数据排重值

    这个使用Redis的set数据结构最合适了,只需要不断地将数据往set中扔就行了,set意为集合,所以会自动排重。

    • 5.实时系统,反垃圾系统

    通过上面说到的set功能,你可以知道一个终端用户是否进行了某个操作,可以找到其操作的集合并进行分析统计对比等。没有做不到,只有想不到。

    • 6.Pub/Sub构建实时消息系统

    Redis的Pub/Sub系统可以构建实时的消息系统,比如很多用Pub/Sub构建的实时聊天系统的例子。

    • 7.构建队列系统

    使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。

    • 8.缓存

    缓存不多做解释,性能优于Memcached(在某些方面,并不是全面优于),数据结构更多样化。

    博客著作权归本作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    相关文章

      网友评论

          本文标题:Redis(一)之入门详解

          本文链接:https://www.haomeiwen.com/subject/peohjctx.html