zoukankan      html  css  js  c++  java
  • NOSQL之REDIS

    Redis是NoSQL中比较常典型的一个非关系型数据库,在日常工作中也是最为常见的。Redis是一个由C语言编写的开源的、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

    https://db-engines.com/en/ranking

    一、安装及启动Redis

    由于我们日常中最多使用redis的环境是在linux中,所以这里主要来看linux下的安装方法。

    1、下载并安装Redis

    我们可以使用wget下载,也可以将redis的包下载下来并且导入到linux中

    $ wget http://download.redis.io/releases/redis-2.8.17.tar.gz
    $ yum install gcc tcl -y
    $ tar xzf redis-2.8.8.tar.gz
    $ cd redis-4.0.8
    $ make 
    $ mkdir /usr/local/redis
    $ make install PREFIX=/usr/local/redis

    2、启动redis

    ./redis-server

    默认启动redis使用的是默认配置,端口号为6379,密码为空。如果需要后台启动的话,可以使用nohup来启动。

    nohup redis-server &

    当然,如果需要指定redis的配置文件,那我们可以在启动命令中指定好配置文件就可以。

    nohup redis-server /usr/local/redis/redis.conf &

    3、停止redis

    redis-cli shutdown

    4、redis配置

    # Protected mode is a layer of security protection, in order to avoid that
    # Redis instances left open on the internet are accessed and exploited.
    #
    # When protected mode is on and if:
    #
    # 1) The server is not binding explicitly to a set of addresses using the
    #    "bind" directive.
    # 2) No password is configured.
    #
    # The server only accepts connections from clients connecting from the
    # IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain
    # sockets.
    #
    # By default protected mode is enabled. You should disable it only if
    # you are sure you want clients from other hosts to connect to Redis
    # even if no authentication is configured, nor a specific set of interfaces
    # are explicitly listed using the "bind" directive.
    protected-mode yes
    
    # Accept connections on the specified port, default is 6379 (IANA #815344).
    # If port 0 is specified Redis will not listen on a TCP socket.
    port 6379
    
    # Unix socket.
    #
    # Specify the path for the Unix socket that will be used to listen for
    # incoming connections. There is no default, so Redis will not listen
    # on a unix socket when not specified.
    #
    # unixsocket /tmp/redis.sock
    # unixsocketperm 700
    
    # Close the connection after a client is idle for N seconds (0 to disable)
    timeout 0
    
    # TCP keepalive.
    #
    # If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
    # of communication. This is useful for two reasons:
    #
    # 1) Detect dead peers.
    # 2) Take the connection alive from the point of view of network
    #    equipment in the middle.
    #
    # On Linux, the specified value (in seconds) is the period used to send ACKs.
    # Note that to close the connection the double of the time is needed.
    # On other kernels the period depends on the kernel configuration.
    #
    # A reasonable value for this option is 300 seconds, which is the new
    # Redis default starting with Redis 3.2.1.
    tcp-keepalive 300
    
    # By default Redis does not run as a daemon. Use 'yes' if you need it.
    # Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
    # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
    # 启用守护进程后,Redis会把pid写到一个pidfile中,在/var/run/redis.pid
    daemonize yes
    
    # Set the number of databases. The default database is DB 0, you can select
    # a different one on a per-connection basis using SELECT <dbid> where
    # dbid is a number between 0 and 'databases'-1
    databases 16
    
    ################################ SNAPSHOTTING  ################################
    #
    # Save the DB on disk:
    #
    #   save <seconds> <changes>
    #
    #   Will save the DB if both the given number of seconds and the given
    #   number of write operations against the DB occurred.
    #
    #   In the example below the behaviour will be to save:
    #   after 900 sec (15 min) if at least 1 key changed
    #   after 300 sec (5 min) if at least 10 keys changed
    #   after 60 sec if at least 10000 keys changed
    #
    #   Note: you can disable saving completely by commenting out all "save" lines.
    #
    #   It is also possible to remove all the previously configured save
    #   points by adding a save directive with a single empty string argument
    #   like in the following example:
    #
    #   save ""
    
    save 900 1
    save 300 10
    save 60 10000
    
    
    # Compress string objects using LZF when dump .rdb databases?
    # For default that's set to 'yes' as it's almost always a win.
    # If you want to save some CPU in the saving child set it to 'no' but
    # the dataset will likely be bigger if you have compressible values or keys.
    rdbcompression yes
    
    # The filename where to dump the DB
    dbfilename dump.rdb
    
    # The working directory.
    #
    # The DB will be written inside this directory, with the filename specified
    # above using the 'dbfilename' configuration directive.
    #
    # The Append Only File will also be created inside this directory.
    #
    # Note that you must specify a directory here, not a file name.
    dir ./
    
    
    

    5、连接redis

    远程连接redis,可以使用redis自带的工具redis-cli,具体使用方法如下:

    redis-cli -h 127.0.0.1 -p 6379 -n 0
    
     -h <hostname> Server hostname (default: 127.0.0.1).
     -p <port> Server port (default: 6379).
     -a <password> Password to use when connecting to the server.
     --help 显示帮助信息
    
    切换数据库:
    select 0
    select 10
    

    6、redis常用命令

    Redis 是一个高性能的key-value数据库,和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。不过既然redis是一个数据库,那么也就逃脱不开增删改查的操作,接下来把每种数据类型常用的增删改查命令列举一次。

    如果对某个命令不知道该如何使用的时候可以使用–help来查询如:

    help set
    
     DEL key [key ...]
     summary: Delete a key
     since: 1.0.0
     group: generic
     KEYS pattern
     summary: Find all keys matching the given pattern
     since: 1.0.0
     group: generic
    
     RENAME key newkey
     summary: Rename a key
     since: 1.0.0
     group: generic
    
     MOVE key db
     summary: Move a key to another database
     since: 1.0.0
     group: generic
    
     EXPIRE key seconds
     summary: Set a key's time to live in seconds
     since: 1.0.0
     group: generic
    
     EXISTS key [key ...]
     summary: Determine if a key exists
     since: 1.0.0
     group: generic
    

    (1)String(字符串)

    redis中最简单的数据类型,可以存储文字、数字、浮点数还可以进行二进制的存储,value存储最大数据量为512M。

    APPEND
     APPEND key value
     summary: Append a value to a key
     since: 2.0.0
     group: string
    在一个key的值后面追加上value内容
    
    GET
     GET key
     summary: Get the value of a key
     since: 1.0.0
     group: string
    获取key的值
    
    GETRANGE
     GETRANGE key start end
     summary: Get a substring of the string stored at a key
     since: 2.4.0
     group: string
    获取key值的切片 从start开始到end结束
    
    GETSET
     GETSET key value
     summary: Set the string value of a key and return its old value
     since: 1.0.0
     group: string
    将value作为key的值写入,并将key的旧值返回
    
    INCR
     INCR key
     summary: Increment the integer value of a key by one
     since: 1.0.0
     group: string
    给key的int值加1,如果这个key没有存在,则会先初始化一个0,然后再加1
    
    INCRBY
     INCRBY key increment
     summary: Increment the integer value of a key by the given amount
     since: 1.0.0
     group: string
    将 key所储存的值加上增量 increment,如果key的值不是int类型,则报错
    
    MGET
     MGET key [key ...]
     summary: Get the values of all the given keys
     since: 1.0.0
     group: string
    同时获取多个key
    
    MSET
     MSET key value [key value ...]
     summary: Set multiple keys to multiple values
     since: 1.0.1
     group: string
    同时写入多个key
    
    MSETNX
     MSETNX key value [key value ...]
     summary: Set multiple keys to multiple values, only if none of the keys exist
     since: 1.0.1
     group: string
    只有在key不存在的时候才可以同时写入多个key值
    
    PSETEX
     PSETEX key milliseconds value
     summary: Set the value and expiration in milliseconds of a key
     since: 2.6.0
     group: string
    写入一个值,但是只有设置的毫秒的有效期,超过后会被删除
    
    SET
     SET key value [EX seconds] [PX milliseconds] [NX|XX]
     summary: Set the string value of a key
     since: 1.0.0
     group: string
    写入一个值
    SETEX
     SETEX key seconds value
     summary: Set the value and expiration of a key
     since: 2.0.0
     group: string
    写入一个值,并且有设置的有效期
    
    SETNX
     SETNX key value
     summary: Set the value of a key, only if the key does not exist
     since: 1.0.0
     group: string
    将 key 的值设为value,当且仅当key不存在
    SETRANGE
     SETRANGE key offset value
     summary: Overwrite part of a string at key starting at the specified offset
     since: 2.2.0
     group: string
    用value参数覆写(overwrite)给定key所储存的字符串值,从偏移量offset开始。
    STRLEN
     STRLEN key
     summary: Get the length of the value stored in a key
     since: 2.2.0
     group: string
    返回key所储存的字符串值的长度。
    

    (2)Hash(哈希)

    hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。Redis 中每个 hash 可以存储 232 – 1 键值对(40多亿)。

    HDEL
     HDEL key field [field ...]
     summary: Delete one or more hash fields
     since: 2.0.0
     group: hash
    删除哈希表key中的一个或多个指定域,不存在的域将被忽略。
    
    HEXISTS
     HEXISTS key field
     summary: Determine if a hash field exists
     since: 2.0.0
     group: hash
    判断哈希表key中的field是否存在
    
    HGET
     HGET key field
     summary: Get the value of a hash field
     since: 2.0.0
     group: hash
    获取哈希表key中的field
    
    HGETALL
     HGETALL key
     summary: Get all the fields and values in a hash
     since: 2.0.0
     group: hash
    获取哈希表key中的所有域和值
    
    HINCRBY
     HINCRBY key field increment
     summary: Increment the integer value of a hash field by the given number
     since: 2.0.0
     group: hash
    为哈希表key中的域field的值加上增量increment。
    
    HKEYS
     HKEYS key
     summary: Get all the fields in a hash
     since: 2.0.0
     group: hash
    返回哈希表key中的所有域。
    
    HLEN
     HLEN key
     summary: Get the number of fields in a hash
     since: 2.0.0
     group: hash
    返回哈希表key中域的数量。
    
    HMGET
     HMGET key field [field ...]
     summary: Get the values of all the given hash fields
     since: 2.0.0
     group: hash
    返回哈希表key中,一个或多个给定域的值。
    
    HMSET
     HMSET key field value [field value ...]
     summary: Set multiple hash fields to multiple values
     since: 2.0.0
     group: hash
    同时将多个field-value(域-值)对设置到哈希表key中。
    
    HSET
     HSET key field value
     summary: Set the string value of a hash field
     since: 2.0.0
     group: hash
    将哈希表key中的域field的值设为value 
    
    HSETNX
     HSETNX key field value
     summary: Set the value of a hash field, only if the field does not exist
     since: 2.0.0
     group: hash
    将哈希表key中的域field的值设置为value,当且仅当域field不存在。
    
    HVALS
     HVALS key
     summary: Get all the values in a hash
     since: 2.0.0
     group: hash
    返回哈希表key中所有的域

    参考:http://doc.redisfans.com/

    7、监控redis

    • 图形化监控工具:TreeSoft
    • 命令行监控:
      • 吞吐量
        • Redis提供的INFO命令不仅能够查看实时的吞吐量(ops/sec),还能看到一些有用的运行时信息。下面用grep过滤出一些比较重要的实时信息,比如已连接的和在阻塞的客户端、已用内存、拒绝连接、实时的tps和数据流量等:
    [root@liml redis]# /usr/local/redis/redis-cli -h 127.0.0.1 -p 6380 -a 123456 info |
    > grep -e "connected_clients" -e "blocked_clients" -e "used_memory_human" 
    -e "used_memory_peak_human" -e "rejected_connections" -e "evicted_keys" 
    -e "instantaneous"
    connected_clients:3    #连接数
    blocked_clients:0    #阻塞连接数
    used_memory_human:3.37M    # redis占用内存
    used_memory_peak_human:3.37M    #redis占用内存峰值
    instantaneous_ops_per_sec:192    #每秒处理请求数
    instantaneous_input_kbps:11.82    #每秒读字节数
    instantaneous_output_kbps:0.75    #每秒写字节数
    rejected_connections:0     #拒绝连接数
    evicted_keys:0        #运行以来删除的key数量
    
      • 延迟
        • 监控redis的延迟可以使用redis提供的ping命令来不断的ping服务器,并且记录服务器响应ping的时间。
    [root@liml ~]# /usr/local/redis/redis-cli -h 127.0.0.1 -p 6380 -a 123456  --latency
    min: 0, max: 1, avg: 0.08 (284 samples)
    
    [root@liml ~]# /usr/local/redis/redis-cli -h 127.0.0.1 -p 6380 -a 123456  
    127.0.0.1:6380> monitor
    1522663856.563254 [0 127.0.0.1:34881] "PING"
    1522663856.573585 [0 127.0.0.1:34881] "PING"
    1522663856.583894 [0 127.0.0.1:34881] "PING"
    1522663856.686623 [0 127.0.0.1:34881] "PING"
    1522663856.696851 [0 127.0.0.1:34881] "PING"
    1522663856.707109 [0 127.0.0.1:34881] "PING"
    
      • 持续实时监控
        • 持续监控redis使用的是linux自带的watch命令和我们前面监控命令结合到一起就可以变成持续的实时监控工具了。
    # 先将前面的命令保存到一个shell脚本中,
    vi testredis.sh 
    #!/bin/bash
    /usr/local/redis/redis-cli -h 127.0.0.1 -p 6380 -a 123456  info | grep -e "connected_clients" -e "blocked_clients" -e "used_memory_human" -e "used_memory_peak_human" -e "rejected_connections" -e "evicted_keys" -e "instantaneous"
    
    #保存后并给予执行的权限
    chmod 755 testredis.sh
    # 使用watch命令实时监控
    watch -n 1 -d "/usr/local/redis/testredis.sh"
    
      • 慢操作日志
        • SORT、LREM、SUNION等操作在大对象上会非常耗时,使用时要注意参照官方API上每个命令的算法复杂度。和主流数据库提供的慢SQL日志一样,Redis也提供了记录慢操作的日志。注意这部分日志只会计算纯粹的操作耗时。

    8、压力测试redis

    redis-benchmark 

    默认情况下面,基准测试使用单一的 key。在一个基于内存的数据库里, 单一 key 测试和真实情况下面不会有巨大变化。当然,使用一个大的 key 范围空间, 可以模拟现实情况下面的缓存不命中情况。

    这时候我们可以使用 -r 命令。比如,假设我们想设置 10 万随机 key 连续 SET 100 万次,我们可以使用下列的命令:

    ./redis-benchmark -p 6380 -a 123456 -t set  -n 1000 -r 10
    ====== set -n 1 -r 1000 ======
      100000 requests completed in 1.24 seconds
      50 parallel clients
      3 bytes payload
      keep alive: 1
    
    99.88% <= 1 milliseconds
    99.89% <= 2 milliseconds
    99.90% <= 3 milliseconds
    99.95% <= 5 milliseconds
    100.00% <= 5 milliseconds
    80450.52 requests per second
    
    

    有几个因素直接决定 Redis 的性能。它们能够改变基准测试的结果, 所以我们必须注意到它们。一般情况下,Redis 默认参数已经可以提供足够的性能, 不需要调优。

    • 网络带宽和延迟通常是最大短板。建议在基准测试之前使用 ping 来检查服务端到客户端的延迟。根据带宽,可以计算出最大吞吐量。 比如将 4 KB 的字符串塞入 Redis,吞吐量是 100000 q/s,那么实际需要 3.2 Gbits/s 的带宽,所以需要 10 GBits/s 网络连接, 1 Gbits/s 是不够的。 在很多线上服务中,Redis 吞吐会先被网络带宽限制住,而不是 CPU。 为了达到高吞吐量突破 TCP/IP 限制,最后采用 10 Gbits/s 的网卡, 或者多个 1 Gbits/s 网卡。
    • CPU 是另外一个重要的影响因素,由于是单线程模型,Redis 更喜欢大缓存快速 CPU, 而不是多核。这种场景下面,比较推荐 Intel CPU。AMD CPU 可能只有 Intel CPU 的一半性能(通过对 Nehalem EP/Westmere EP/Sandy 平台的对比)。 当其他条件相当时候,CPU 就成了 redis-benchmark 的限制因素。
    • 在小对象存取时候,内存速度和带宽看上去不是很重要,但是对大对象(> 10 KB), 它就变得重要起来。不过通常情况下面,倒不至于为了优化 Redis 而购买更高性能的内存模块。
    • Redis 在 VM 上会变慢。虚拟化对普通操作会有额外的消耗,Redis 对系统调用和网络终端不会有太多的 overhead。建议把 Redis 运行在物理机器上, 特别是当你很在意延迟时候。在最先进的虚拟化设备(VMWare)上面,redis-benchmark 的测试结果比物理机器上慢了一倍,很多 CPU 时间被消费在系统调用和中断上面。
  • 相关阅读:
    NOIP201208同余方程
    NOIP模拟赛 最佳组合
    NOIP模拟赛 拓展
    CF1253E Antenna Coverage(DP)
    LOJ6033「雅礼集训 2017 Day2」棋盘游戏 (博弈论,二分图,匈牙利算法)
    CF582E Boolean Function(DP,状态压缩,FMT)
    CF750G New Year and Binary Tree Paths(DP)
    Codeforces Round 596 题解
    AGC008E Next or Nextnext(组合计数,神奇思路)
    ARC082E ConvexScore(神奇思路)
  • 原文地址:https://www.cnblogs.com/xiaowenshu/p/10237356.html
Copyright © 2011-2022 走看看