美文网首页redisredisnoSQL
Redis服务器搭建

Redis服务器搭建

作者: 64d1c00cca37 | 来源:发表于2017-06-07 23:21 被阅读1081次

    Redis简介

    Redis全称:Remote Dictionary Server(远程数据服务)。Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/popadd/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

    Redis安装配置(Linux平台)

    Redis编译与安装

    在进行redis的编译安装需要先进行 apt-get install make

    1.将Redis开发包上传到Linux系统之中,但是需要注意,由于给出的开发包属于源代码,所以建议解压缩到/usr/local/src目录之中;

    tar -xzvf /srv/ftp/redis-3.2.9.tar.gz -C /usr/local/src/
    

    2.进入到redis源代码所在的安装目录:cd /usr/local/src/redis-3.2.9/
    3.进行程序的编译处理,输入:make
    4.编译完成之后要进行Redis安装,输入:make install
    5.Redis属于内存缓存数据库,那么如果你现在是一台单独的Redis服务器,则应该考虑将所有的可用内存都交给Redis来进行支配,所以理论上还需要执行如下的一行代码:

    echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
    

    本次的操作指的是进行一次内存的分配策略,在进行设置的时候vm.overcommit_memory属性有如下三个取值:

    • 0:表示在进行处理的时候首先要检查是否有足够的内存供应, 如果现在没有足够的内存供应,则无法分配,内存申请失败,如果有可用内存则直接进行申请开辟;
    • 1:表示将所有的内存都交给应用使用,而不关心当前的内存状态如何;
    • 2:表示允许分配超过所有物理内存和交换空间的内存的总和;

    6.将以上的配置写入到内核参数之中:/sbin/sysctl -p
    7.为了方便使用Redis数据库,那么建立一个Redis支持的命令工具目录:

    mkdir -p /usr/local/redis/{bin,conf}
    

    8.通过源代码目录拷贝出Redis所需要的程序运行文件:

    • 拷贝Redis服务启动程序:cp /usr/local/src/redis-3.2.9/src/redis-server /usr/local/redis/bin/
    • 拷贝Redis命令行客户端:cp /usr/local/src/redis-3.2.9/src/redis-cli /usr/local/redis/bin/
    • 性能测试工具:cp /usr/local/src/redis-3.2.9/src/redis-benchmark /usr/local/redis/bin/

    9.拷贝出一个配置文件:

    cp /usr/local/src/redis-3.2.9/redis.conf /usr/local/redis/conf/
    

    Redis数据库配置

    如果要想配置Redis数据库,主要的配置文件就是redis.conf,所有的配置项一定要在此处完成。

    1. Redis作为一个具备有持久化功能的缓存数据库,所以其一定会有一个用于数据存储的目录,那么一般在 Redis 处理的时候会有三类文件需要做保存:Redis运行时的pidRedis相关处理日志、Redis的数据文件,所以建立一个目录用于存放这些数据:
    mkdir -p /usr/data/redis/{run,logs,dbcache}
    

    2.修改redis.conf的配置文件:vim /usr/local/redis/conf/redis.conf

    • 配置Redis运行端口:port 6379
    • 配置Redis是否为后台运行:daemonize yes
    • 设置进程保存路径:pidfile /usr/data/redis/run/redis_6379.pid
    • 设置日志保存目录:logfile "/usr/data/redis/logs/redis.log"
    • Redis支持的数据库个数:databases 16
    • 保存数据文件目录:dir /usr/data/redis/dbcache

    3.启动Redis服务:/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf

    • 如果要启动Redis-Server就必须明确的指明要使用的redis.conf配置文件;

    4.Redis启动会占用6379的端口,所以查看端口:netstat -nptl

    • 此时发现Redis运行的时候是在6379本机下才可以执行,所以无法对外提供服务;

    5.启动Redis客户端:
    方式一:连接本机6739端口的Redis : /usr/local/redis/bin/redis-cli
    方式二:连接远程的格式 : /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379

    6.设置一个数据:set myredis java
    7.取得数据:get myredis
    8.关闭Redis服务:

    • 取得要关闭的Redis服务的进程,而后使用kill直接杀死;
    • 直接使用 killall redis-server 干掉所有的 Redis 服务。

    9、redis日志查看目录:/usr/data/redis/logs

    cat redis.log
    

    Redis数据操作

    Redis支持各种的数据类型,而且Redis操作的速度很快的,在Redis数据库里面有一个redis-benchmark性能测试工具,可以直接使用这个工具来观察Redis使用,该命令所需要的参数如下:

    root@redis-single:~# /usr/local/redis/bin/redis-benchmark --help
    Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]
     -h <hostname>      Server hostname (default 127.0.0.1)
     -p <port>          Server port (default 6379)
     -s <socket>        Server socket (overrides host and port)
     -a <password>      Password for Redis Auth
     -c <clients>       Number of parallel connections (default 50)
     -n <requests>      Total number of requests (default 100000)
     -d <size>          Data size of SET/GET value in bytes (default 2)
     -dbnum <db>        SELECT the specified db number (default 0)
     -k <boolean>       1=keep alive 0=reconnect (default 1)
     -r <keyspacelen>   Use random keys for SET/GET/INCR, random values for SADD
      Using this option the benchmark will expand the string __rand_int__
      inside an argument with a 12 digits number in the specified range
      from 0 to keyspacelen-1. The substitution changes every time a command
      is executed. Default tests use this to hit random keys in the
      specified range.
     -P <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).
     -e                 If server replies with errors, show them on stdout.
                        (no more than 1 error per second is displayed)
     -q                 Quiet. Just show query/sec values
     --csv              Output in CSV format
     -l                 Loop. Run the tests forever
     -t <tests>         Only run the comma separated list of tests. The test
                        names are the same as the ones produced as output.
     -I                 Idle mode. Just open N idle connections and wait.
    
    Examples:
     Run the benchmark with the default configuration against 127.0.0.1:6379:
       $ redis-benchmark
     Use 20 parallel clients, for a total of 100k requests, against 192.168.1.1:
       $ redis-benchmark -h 192.168.1.1 -p 6379 -n 100000 -c 20
     Fill 127.0.0.1:6379 with about 1 million keys only using the SET test:
       $ redis-benchmark -t set -n 1000000 -r 100000000
     Benchmark 127.0.0.1:6379 for a few commands producing CSV output:
       $ redis-benchmark -t ping,set,get -n 100000 --csv
     Benchmark a specific command line:
       $ redis-benchmark -r 10000 -n 10000 eval 'return redis.call("ping")' 0
     Fill a list with 10000 random elements:
       $ redis-benchmark -r 10000 -n 10000 lpush mylist __rand_int__
     On user specified command lines __rand_int__ is replaced with a random integer
     with a range of values selected by the -r option.
    

    范例:下面模拟1000个客户端进行数据的处理

    /usr/local/redis/bin/redis-benchmark -h 127.0.0.1 -p 6379 -c 1000 -d 10 -n 10000
    

    此时的命令之中的具体参数含义如下:

    • -h:要连接的Redis服务器的地址;
    • -p:要连接Redis的运行端口;
    • -c:指的是模拟的客户端数量;
    • -d:每一次操作的数据长度;
    • -n:每一个用户发出的请求数量。

    随后来观察一下当前的测试结果,会包含有如下的信息内容:

    • PING_INLINE: 44247.79 requests per second;
    • SET: 42918.46 requests per second;
    • GET: 43478.26 requests per second;
    • INCR: 42372.88 requests per second;
    • LPUSH: 43290.04 requests per second;
    • RPUSH: 41666.67 requests per second;
    • LPOP: 42918.46 requests per second;
    • RPOP: 44052.86 requests per second;
    • SADD: 43859.65 requests per second;
      ...

    字符串类型

    Redis里面有一个特别重要的命令keys,可以进行全部数据的列出。其中后面的*****表示数据的匹配。

    1、设置新的数据:set KEY VALUE

    set username tom
    

    2、取得对应的数据:get KEY

    get username
    
    • 如果在进行数据查询的时候没有对应的key的内容,则返回的是(nil)数据;
    • 在数据取得的时候没有*****的通配,只有**keys ***命令提供有这一操作。

    3.清空仓库:flushdb
    4.不覆盖设置内容:setnx KEY VALUE

    setnx username JAMES
    setnx username JAMES
    
    • 对于setnx的返回结果有如下两类:0(表示没有设置成功)、1(设置成功);
    • 如果你现在设置的两个数据的key的内容是相同的,默认情况下是会发生有覆盖的问题的;
    set uname james
    set uname tom
    

    5.设置数据保存的有效时间:setnx KEY VALUE

    setex wechat_code 60 3452 
    
    • 现在就表示该设置的内容在60秒之后就会自动销毁。
    • 在实际的使用之中验证码的信息保存就使用了此类数据类型,因为该类型的数据到点后自动消失。
    • 在某一个key具备有指定的有效时间设置之后实际上可以使用ttl key查看当前剩余有效时间,如果该内容已经消失则返回-2,如果没有消失,则返回剩余的时间,或者在有效期内使用persist key,让该key取消有效时间,这个时候如果使用ttl命令查看则返回的结果是-1

    6.设置多个key的内容:mset KYE1 VALUE1 KEY2 VALUE2...

    mset username-110 hello username-120 world username-119 cry
    

    那么此时同时设置有三个key的信息,如果此时设置有相同的key的信息,那么默认会出现覆盖的问题:

    mset username-110 hello1 username-120 world1 username-119 cry1
    

    7.不覆盖设置多个keymsetnx KEY1 VALUE1 KEY2 VALUE2...

    • 包含有一个重复的内容以及两个不重复的内容,因为有一个存在所以返回的是0,并且所有的内容都不允许设置:
    msetnx username-110 hello2 username-1 hello username-2 world
    
    • 包含全部新的内容:现在表示成功返回1
    msetnx username-1 hello username-2 world
    

    8.内容追加:a1end KEY CONTENT

    a1end username-110 world
    

    返回的是当前的内容的长度;
    9.取得指定key的内容长度:strlen KEY

    strlen username-110 
    

    10.删除指定的数据内容:del KEY1 KEY2 ...

    del 110-code username-1 username-99 
    

    如果现在指定的key不存在,也不会影响到程序的执行,只会删除掉存在的key的信息。
    以下为redis执行代码:

    127.0.0.1:6379> set username tom
    OK
    127.0.0.1:6379> get username
    "tom"
    127.0.0.1:6379> flushdb
    OK
    127.0.0.1:6379> setnx username JAMES
    (integer) 1
    127.0.0.1:6379> setnx username JAMES
    (integer) 0
    127.0.0.1:6379> get username
    "best"
    127.0.0.1:6379> set uname james
    OK
    127.0.0.1:6379> set uname tom
    OK
    127.0.0.1:6379> get uname
    "tom"
    127.0.0.1:6379> setex wechat_code 60 3452 
    OK
    127.0.0.1:6379> get wechat_code
    "3452"
    127.0.0.1:6379> get wechat_code
    (nil)
    127.0.0.1:6379> mset username-110 hello username-120 world username-119 cry
    OK
    127.0.0.1:6379> mset username-110 hello1 username-120 world1 username-119 cry1
    OK
    127.0.0.1:6379> get username-110
    "hello1"
    127.0.0.1:6379> msetnx username-110 hello2 username-1 hello username-2 world
    (integer) 0
    127.0.0.1:6379> msetnx username-1 hello username-2 world
    (integer) 1
    127.0.0.1:6379> a1end username-110 world
    (integer) 11
    127.0.0.1:6379> del 110-code username-1 username-99
    (integer) 1
    

    Hash数据类型

    Hash是一种最为常见的数据类型,其保存的数据结构为key = value,但是需要提醒的是这个时候的keyvalue并不是redis中的keyvalue,hash是作为一种类型,可以这样理解关系:RedisKey = HashValue,利用Hash类型可以保存更多的数据。
    1.存放Hash数据:hset hash-key sub-key1 value1
    设置一个Hash类型,保存一个用户的用户名和真实姓名:
    结构:mid为用户名的保存的属性名称、7396为真实的用户名;

    hset member mid 7396
    hset member name tom
    

    2.取得散列包含的所有键值内容:hgetall hash-key
    它在进行数据排列的时候采用的模式为:hash-key、hash-value、hash-key、hash-value

    hgetall member
    

    取得指定key的内容:

    • 取得指定key中的mid的数据:hget member mid
    • 取得指定key中的name的数据:hget member name

    3.默认情况下hset会进行覆盖设置,那么使用hsetnx就可以避免掉这种覆盖设置的问题:

    • 设置重复数据:hsetnx member mid hello,返回的结果为0false);
    • 设置不重复的数据:hsetnx member-aa mid hello,返回结果为1true)。
    • 这个时候所有的**keys * **可以见到的内容只是所有的key的名称。

    4.数据批量设置:hmset member-1 name wusheng age 55 province hb
    5.判断某个key的某个属性是否存在:hexists member-1 school
    6.取得全部的数据的成员个数:hlen member
    7.删除指定的key的内容:hdel member-1 age,name
    8.取得一个hash中的所有的key(成员)内容:hkeys member-1
    9.取得指定hash中的所有内容:hvals member

    以下为具体代码操作:

    127.0.0.1:6379> hset member mid 7396
    (integer) 1
    127.0.0.1:6379> hset member name tom
    (integer) 1
    127.0.0.1:6379> hgetall member
    1) "mid"
    2) "7396"
    3) "name"
    4) "tom"
    127.0.0.1:6379> hget member mid
    "7396"
    127.0.0.1:6379> hsetnx member mid hello
    (integer) 0
    127.0.0.1:6379> hsetnx member-aa mid hello
    (integer) 1
    127.0.0.1:6379> keys *
    1) "username-120"
    2) "username-110"
    3) "member"
    4) "username-2"
    5) "username"
    6) "member-aa"
    7) "uname"
    8) "username-119"
    127.0.0.1:6379> hmset member-1 name wusheng age 15 province beijing
    OK
    127.0.0.1:6379> hexists member-1 school
    (integer) 0
    127.0.0.1:6379> hlen member
    (integer) 2
    127.0.0.1:6379> hdel member-1 age,name
    (integer) 0
    127.0.0.1:6379> hkeys member-1
    1) "name"
    2) "age"
    3) "province"
    127.0.0.1:6379> hvals member
    1) "7396"
    2) "tom"
    

    数字操作

    普通数据类型

    • 自增处理:incr KEY
    • 自增指定数据:incrby KEY num
    • 自减处理:decr KEY
    • 自减指定数据:decrby KEY
      数据类型
    • 数据加法:hincrby 对象 KEY 数字

    1.如果要进行数字的操作,那么肯定要设置两个数字的内容:

    • 设置一个基本类型:set shopcar-pid 100
    • 设置一个Hash类型:hset sc pid-72378 100

    2.进行普通数据类型的数字操作:

    • 自增1处理:incr shopcar-pid,随后会返回当前增长后的数据内容。
    • 默认增长为1,现在要求增长为5incrby shopcar-pid 5
    • 自减1处理:decr shopcar-pid
    • 自减指定的数据:decrby shopcar-pid 100

    3.进行Hash数据类型的数字操作:hincrby sc pid-72378 1实际上整个数字操作里面只需要记住两个命令:incrbyhincrby就够了。

    127.0.0.1:6379> set shopcar-pid 100
    OK
    127.0.0.1:6379> hset sc pid-72378 100
    (integer) 1
    127.0.0.1:6379> incr shopcar-pid
    (integer) 101
    127.0.0.1:6379> incrby shopcar-pid 200
    (integer) 301
    127.0.0.1:6379> incrby shopcar-pid 5
    (integer) 306
    127.0.0.1:6379> decr shopcar-pid
    (integer) 305
    127.0.0.1:6379> decrby shopcar-pid 100
    (integer) 205
    127.0.0.1:6379> hincrby sc pid-72378 1
    (integer) 101
    

    List数据类型

    List数据类型是一种比较麻烦的处理操作。在实际的项目开发里面,List就是一个链表结构,那么链表结构的时间复杂度是n,而且在进行链表数据处理的时候主要是进行内容的保存、节点的设置、递归遍历。

    1.左边压入创建一个描述关键字的List集合:lpush javaee redis java hello happy word cloud
    push属于入栈,栈的特点是先进后出;
    2.进行指定范围的链表数据输出:lrange javaee 0 -1,如果设置为-1则表示输出全部的内容。
    3.右边压入进行入栈处理:rpush javaee 1 2 3 4 5 6 7
    4.在指定元素(hello)上追加内容:
    在指定元素前追加:linsert javaee before hello hello-before

    • 在指定元素后追加:linsert javaee after hello hello-after
    • 如果此时你保存的集合内容存放有重复的数据,则以第一个数据为准进行保存。

    5.删除数据:lrem javaee 5 hello
    6.保留指定范围的数据:ltrim javaee 0 9,范围编号不在0 ~ 9之间的所有数据将被删除掉;
    7.栈顶元素出栈:lpop javaee
    8.栈底元素出栈:rpop javaee
    9.将移除的数据保存到另一个集合:rpoplpush javaee new_javaee
    表示将javaee的集合中的栈底的一个元素出栈,而后压入到new_javaee这个集合的栈顶。
    10.取得指定索引对应的数据:lindex javaee 0
    11.取得集合个数:llen javaee

    127.0.0.1:6379> lpush javaee redis java hello happy word cloud
    (integer) 6
    127.0.0.1:6379> lrange javaee 0 -1
    1) "cloud"
    2) "word"
    3) "happy"
    4) "hello"
    5) "java"
    6) "redis"
    127.0.0.1:6379> rpush javaee 1 2 3 4 5 6 7
    (integer) 13
    127.0.0.1:6379> linsert javaee before hello hello-before
    (integer) 14
    127.0.0.1:6379> linsert javaee after hello hello-after
    (integer) 15
    127.0.0.1:6379> lrange javaee 0 -1
     1) "cloud"
     2) "word"
     3) "happy"
     4) "hello-before"
     5) "hello"
     6) "hello-after"
     7) "java"
     8) "redis"
     9) "1"
    10) "2"
    11) "3"
    12) "4"
    13) "5"
    14) "6"
    15) "7"
    127.0.0.1:6379> lrem javaee 5 hello
    (integer) 1
    127.0.0.1:6379> ltrim javaee 0 9
    OK
    127.0.0.1:6379> lrange javaee 0 -1
     1) "cloud"
     2) "word"
     3) "happy"
     4) "hello-before"
     5) "hello-after"
     6) "java"
     7) "redis"
     8) "1"
     9) "2"
    10) "3"
    127.0.0.1:6379> lpop javaee
    "cloud"
    127.0.0.1:6379> rpop javaee
    "3"
    127.0.0.1:6379> rpoplpush javaee new_javaee 
    "2"
    127.0.0.1:6379> lrange new_javaee 0 -1
    1) "2"
    127.0.0.1:6379> lindex javaee 0
    "word"
    127.0.0.1:6379> llen javaee
    (integer) 7
    

    Set数据类型

    Set也是一种常见的数据类型,其最大的特征是基于数据的集合比对处理,例如:可以实现数据的交集、并集、差集。
    1.向集合之中追加新元素:sadd user-redis a b c d e
    此时向该集合之中追加有五个元素,可以把每一个元素想象为一个用户名;
    2.查询set集合处理:smembers user-redisList集合是有序的,而Set集合是无序的。
    3.删除set集合元素:srem user-redis a
    4.从集合中弹出元素(该元素会自动进行删除处理):spop user-redis
    5.返回两个集合的差集合:
    准备出第一个集合:sadd user-redis a b c d e
    准备出第二个集合:sadd user-admin a c e x y z
    进行差运算:sdiff user-redis user-admin
    6.保存差集的运行结果到其它集合:sdiffstore user-admin-redis user-admin user-redis
    user-adminuser-redis两个用户的数据进行差集的计算处理,并且将结果保存到user-admin-redis集合中;
    查看差集的保存:smembers user-admin-redis
    7.交集运算:sinter user-redis user-admin
    将交集保存到指定的集合里面去:sinterstore user-admin-redis-inter user-admin user-redis
    8.并集运算:sunion user-admin user-redis
    将并集保存到指定的集合里面:sunionstore user-admin-redis-union user-admin user-redis
    9.弹出数据到另外的集合中:smove user-redis user-redis-tmp a
    10.返回集合个数:scard user-redis
    11.判断指定的集合中是否包含有指定的元素存在:sismember user-redis b,如果存在返回 1,不存在返回 0
    12.虽然返回集合中的数据:srandmember user-redis 3
    其中后面可以设置返回的数据个数,如果不设置默认为 1

    SortedSet集合

    Set集合的最大特征是可以进行数据比对,但是Set数据本身是属于无序的保存,所以如果需要进行数据的顺序保存,那么可以采用SortedSet,这个也不算是一个顺序保存,更多的情况下该集合可以保存有一个分数,而这个分数的操作就可以作为一些数据的统计结果出现。

    1.增加SortedSet数据:

    zadd user-redis 1 pid-1 
    zadd user-redis 1 pid-2 
    zadd user-redis 1 pid-3
    

    现在假设这些商品的信息该用户只看了一次,所以每一个数据的分数为1
    2.取得sortedSet集合中的全部数据:
    显示所有的数据的元素:zrange user-redis 0 -1
    显示每一个元素和其对应的分数:zrange user-redis 0 -1 withscores
    也可以输出指定范围的数据:zrange user-redis 0 2 withscores
    3.从集合里面删除数据:zrem user-redis pid-
    4.元素分数的增长:zincrby user-redis 5 pid-1,会返回有当前增长后的数据内容;
    5.取得指定元素的索引内容:zrank user-redis pid-1,索引值从0开始;
    6.数据反转处理取得索引:zrevrank user-redis pid-1
    7.反转后取得数据:zrevrange user-redis 0 -1 withscores
    8.根据分数范围取得数据:
    闭区间处理:zrangebyscore user-redis 3 6 withscores,包含了36
    开区间处理:zrangebyscore user-redis (3 (6 withscores
    设置一个范围:zrangebyscore user-redis 1 10 withscores limit 0 2
    9.取得指定分数范围的数据量:zcount user-redis 2 8
    10.取得指定key中的集合数量:zcard user-redis
    取得指定的分析的keykeys *
    11.根据索引下标删除数据:zremrangebyrank user-redis 0 5
    总结

    1.基本类型(Stringint):基本类型的操作更加适合于用户进行短期的数据存储,因为在实际的开发之中,字符串可以进行各种复杂操作,而且字符串也可以描述出各种数据的含义。那么在实际的开发之中,可以利用此类型使用Nginx的集群数据保存、Shiro的集群数据保存、SpringData数据保存(序列化)、JSON数据的保存;
    2.hash类型:hash类型更多的情况下描述的是一个结构化的信息,但是这种结构化的信息个人认为不如对象序列化好用,但是至少需要知道Hash这样的类型可以进行内容的详细分类;
    3.List(栈、队列):在实际的开发之中可以利用此类型实现消息队列的功能,或者进行缓冲的功能,很多公司有可能不直接使用消息队列中间件,而直接利用Redis代替。
    4.Set数据类型:最大的支持功能在于集合的运算上,例如:相似度检测、好友推荐等等,都可以通过这种集合的处理方式来完成,应用案例:新浪微博。
    5.SortedSet:主要进行数据的流式分析;
    就以用户浏览商品操作为例。通过分数来进行商品推荐。

    Redis事务处理

    Redis本身支持事务处理,但是这种支持的事务处理本身是存在有设计缺陷的,而且与传统的关系型数据库的事务处理有些不同,首先先来看一下Redis中的事务支持命令:

    • 打开事务:multi
    • 取消事务:discard
    • 提交事务:exec
      范例:观察Redis中的事务

    设置一个数据:set age 30
    打开事务支持:multi
    QUEUED进行数据操作:set age 300
    QUEUED进行数据操作:set age 3000
    关闭事务:discard

    一旦开启了Redis的事务控制,则表示所有的更新操作都要追加到一个更新队列之中。由于现在在执行完更新之后发现数据本身出现有问题了,所以选择了关闭事务,一旦事务关闭之后那么该操作将会回滚到最初的状态。

    范例:执行事务提交

    设置一个数据:set age 30
    打开事务支持:multi
    QUEUED进行数据操作:set age 50
    提交事务:exec

    如果在事务开启状态下进行了更新处理,随后只有执行了exec指令后才表示事务真正提交,才会真正影响到原始数据。 但是需要提醒的是,Redis设计之初就是不考虑事务的,所以以上的事务只能够说是Redis的一个玩笑,因为这种事务本身设计的并不完善。

    设置一个数据:set id redis
    打开事务支持:multi
    QUEUED进行数据操作:incr id
    QUEUED进行数据操作:set age 500
    提交事务:exec

    这个时候一旦提交事务一定会出现错误信息ERR value is not an integer or out of range,因为id的数据不是数字,所以无法进行数字的增长。而且一旦出现了错误之后,其它的更新操作依然可以正常完成。

    Redis乐观锁

    在数据库执行操作的时候,为了保证数据的一致性,即:A用户更新数据的时候B用户不能够更新。所谓的锁在数据库设计上分为两种:

    • 悲观锁:基于数据库的操作实现;
    SELECT * FROM member WHERE mid=1 FOR UPDATE ;
    
    • 乐观锁:基于算法的实现,在数据表上追加一个锁的处理列; 在Redis里面是直接支持有乐观锁的,如果要想观察乐观锁的处理,则可以打开两个不同的Session来进行处理。

    1.第一个Session执行如下的操作:

    设置一个数据:set age 30
    进行该数据的监听:watch age
    启用事务:multi

    这个时候并没有对age数据做任何的修改;

    2.第二个session对数据进行修改操作:

    覆盖age数据:set age 500
    取得age数据:get age

    3.第一个session对数据修改:

    修改数据:set age 60
    提交事务:exec

    此时由于第二个Session已经更新了原始的数据,那么就表示该原始数据上的一个标记列更新,这样当第一个session再进行更新的时候会发现返回了(nil),意味着本次更新失败。

    Redis密码配置

    如果说你现在的Redis没有进行认证的处理操作,那么所有的程序都可以进行连接。直接使用redis-cli命令只需要设置上主机名称和端口号就可以进行连接处理。那么为了安全必须要设置密码。 在Redis数据库设计的时候并没有像其它数据库那样准备了一堆复杂的密码或者权限的概念,在Redis里面只需要设置一个认证密码就可以解决问题。
    1.修改redis.conf配置文件:vim /usr/local/redis/conf/redis.conf,追加以下内容:

    requirepass redisjava
    

    2.随后关闭掉redis服务并且重新启动:

    • 关闭redis服务:killall redis-server
    • 重新启动redis服务:/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf

    3.登录redis服务器:/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379

    • 这个时候发现可以正常登录Redis数据库,但是一旦执行数据操作**keys ***,那么就会出现如下错误信息:
    (error) NOAUTH Authentication required.
    
    • 此时可以执行如下命令进行认证处理:auth redisjava
      4.直接在登录客户端的时候进行认证编写,使用一个-a的参数即可:
    /usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 -a redisjava
    

    所有的Redis服务一定要有认证密码,而且作为Redis集群设计的时候一定要将所有密码统一。

    Redis性能监控

    Redis是作为缓存数据库使用,那么一旦在开发之中使用了Redis,就表示有可能会大面积的去向Redis里面保存数据,那么现在如果要想知道当前的运行状态,那么就需要对其进行监控处理,如果要进行Redis监控,必须通过其它组件完成,本次使用一个redis-stat工具实现Redis监控操作,这个工具可以直接通过github找到。

    • redis-stat下载地址:https://github.com/junegunn/redis-stat
      1.为了更加清楚的发现redis-stat特点,下面建立三个Redis运行进程,模拟方式很简单,配置不同的Redis端口即可,也就是说你需要准备出不同的redis.conf配置文件;
      2.建立redis数据的保存目录,要求可以同时保存三个Redis进程;
    mkdir -p /usr/data/redis/{redis-6379,redis-6380,redis-6381}/{run,logs,dbcache}
    

    3.将之前的redis.conf配置文件拷贝一份:

    cp /usr/local/redis/conf/redis.conf /usr/local/redis/conf//redis-6379.conf
    

    4.编辑每一个配置文件,修改各自的内容,以redis-6379为例:vim /usr/local/redis/conf/redis-6379.conf

    取消外网访问限制:# bind 127.0.0.1
    设置端口:port 6379
    设置pid保存路径:pidfile /usr/data/redis/redis-6379/run/redis_6379.pid
    设置日志文件路径:logfile "/usr/data/redis/redis-6379/logs/redis.log"
    数据文件目录:dir /usr/data/redis/redis-6379/dbcache

    5.将redis-6379.conf复制为redis-6380.conf、redis-6381.conf

    cp /usr/local/redis/conf/redis-6379.conf /usr/local/redis/conf//redis-6380.conf 
    cp /usr/local/redis/conf/redis-6379.conf /usr/local/redis/conf//redis-6381.conf
    

    随后进入到每一个配置文件进行6379内容的更新:1,$s/6379/6380/g1,$s/6379/6381/g
    6.启动所有的Redis服务:

    /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6379.conf 
    /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf 
    /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6381.conf
    

    7.通过GITHUB下载redis-stat开发包:

    • 如果要想使用redis-stat检测包必须下载ruby相关环境:apt-get install ruby ruby-dev rubygems
    • 将该工具下载到/usr/local目录之中:cd /usr/local/
    • 进行redis-stat的下载:git clone https://github.com/junegunn/redis-stat.git

    8.下载下来的redis-stat里面实际上只有一个执行命令:/usr/local/redis-stat/bin/redis-stat

    • 进入到redis-stat所在目录:cd /usr/local/redis-stat/bin; 如果要想使用这个命令则必须使用 ruby 进行该命令的处理:gem install redis-stat

    9.启动 redis-stat 工具进行监听控制:

    /usr/local/redis-stat/bin/redis-stat 192.168.125.136:6379 192.168.125.136:6380 192.168.125.136:6381 -a redisjava
    
    redis-stat检测工具

    10.该工具还支持WEB启动查看,也就是说它内部自动提供有一个HttpServer

    /usr/local/redis-stat/bin/redis-stat 192.168.125.136:6379 192.168.125.136:6380 192.168.125.136:6381 -a redisjava --server=80 --daemon --verbose
    

    启动浏览器:http://192.168.125.136

    浏览器客户端

    11.使用redis提供的工具来做测试:

    /usr/local/redis/bin/redis-benchmark -h 192.168.125.136 -p 6379 -a redisjava -c 1000 -d 10 -n 10000
    /usr/local/redis/bin/redis-benchmark -h 192.168.125.136 -p 6380 -a redisjava -c 1000 -d 10 -n 10000
    /usr/local/redis/bin/redis-benchmark -h 192.168.125.136 -p 6381 -a redisjava -c 1000 -d 10 -n 10000
    
    性能测试

    相关文章

      网友评论

        本文标题:Redis服务器搭建

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