[关闭]
@sasaki 2016-01-27T10:32:27.000000Z 字数 16879 阅读 3634

NoSQL与Redis分布式缓存数据库

Redis


版本控制

  1. @Title NoSQLRedis分布式缓存数据库
  2. @Version v1.0
  3. @Timestamp 2015-01-19 16:42
  4. @Author Nicholas
  5. @Mail redskirt@outlook.com

一、NoSQL介绍

  1. 简介
    NoSQL是以key-value形式存储,和传统的关系型数据库不一样,不一定遵循传统数据库的一些基本要求,比如SQL标准、ACID属性、表结构等,这类数据库主要有以下特点:非关系型、分布式、开源、水平可拓展等。

  2. 适用场景

    • 对数据库高并发读写
    • 对海量数据的高效率存储和访问
    • 对数据的高可扩展性和高可用性

二、Redis概述

  1. Redis是一个Key-Value的存储系统。它支持存储的value类型很多,包括string(字符串)、list(链表)、set(集合)、zset(有序集合)。这些数据类型都支持p**ush/pub、add/remove**及取秶和并集及更丰富的操作,Redis支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中,它也可以周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件

  2. Redis适用场合

    1)应用直接访问Redis
    QQ截图20160119165246.jpg-219.3kB

    2)应用程序直接访问Redis,当Redis访问失败时访问MySQL
    QQ截图20160119165543.jpg-388.1kB

    • 取最新N个数据的操作
    • 排行榜应用,取TopN操作
    • 需要精确设定过期时间的应用
    • 计数器应用
    • Uniq操作,获取某段时间所有数据排重值
    • 实时系统,反垃圾系统
    • Pub/Sub构建实时消息系统
    • 构建队列系统
    • 缓存
  3. Redis主要配置含义

    • daemonize:是否以后台daemon方式运行
    • pidfile:pid文件位置
    • port:监听的端口号
    • timeout:请求超时时间
    • loglevel:log信息级别
    • logfile:log文件位置
    • databases:开启数据库的数量
    • save * :保存快照的频率,第一个表示多长时间,第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。
    • rdbcompression:是否使用压缩
    • dbfilename:数据快照文件名(只是文件名,不包括目录)
    • dir:数据快照的保存目录(这个是目录)
    • appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率
    • appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步)

三、Redis应用

  1. Redis数据类型
    string:一个Key对应一个Value,string类型是二进制安全的。Redis的string可以包含任何对象,比如jpg图片或序列化的对象。

    1. [root@master ~]# netstat -tunpl|grep 6379
    2. tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 28424/redis-server
    3. tcp 0 0 :::6379 :::* LISTEN 28424/redis-server
    4. [root@master redis-3.0.6]# redis-cli
    5. # set
    6. 127.0.0.1:6379> set str hello
    7. OK
    8. # get
    9. 127.0.0.1:6379> get str
    10. "hello"
    11. # setnx:设置key对应的值为string类型的value,如果key已经存在,返回0,nx是not exist的意思
    12. 127.0.0.1:6379> setnx str hello
    13. (integer) 0
    14. # setex:设置key对应的值为string类型的value,并指定此键值对应的有效期
    15. 127.0.0.1:6379> setex str_ 10 test
    16. OK
    17. 127.0.0.1:6379> get str_
    18. "test"
    19. 127.0.0.1:6379> get str_
    20. (nil)
    21. # setrange:设置指定key的value值的子字符串
    22. 127.0.0.1:6379> set num 123456789
    23. OK
    24. 127.0.0.1:6379> get num
    25. "123456789"
    26. 127.0.0.1:6379> setrange num 6 666
    27. (integer) 9
    28. 127.0.0.1:6379> get num
    29. "123456666"
    30. # mset:设置多个key的值,成功返回ok,失败返回0表示没有任何值被设置
    31. 127.0.0.1:6379> mset key1 liuwei key2 nicholas key3 sasaki
    32. OK
    33. 127.0.0.1:6379> get key1
    34. "liuwei"
    35. 127.0.0.1:6379> get key2
    36. "nicholas"
    37. 127.0.0.1:6379> get key3
    38. "sasaki"
    39. # mset x:设置多个key的值,成功返回ok,失败返回0表示没有任何值被设置,但是不会覆盖已存在的key
    40. 127.0.0.1:6379> msetnx key1 liuwei_ key4 test
    41. (integer) 0
    42. 127.0.0.1:6379> get key1
    43. "liuwei"
    44. 127.0.0.1:6379> get key4
    45. (nil)
    46. # get:获取key的string值,若不存在返回nil
    47. # getset:设置key值并且返回key的旧值
    48. 127.0.0.1:6379> getset key1 test
    49. "liuwei"
    50. 127.0.0.1:6379> get key1
    51. "test"
    52. # getrange:获取key的子字符串
    53. 127.0.0.1:6379> get key2
    54. 127.0.0.1:6379> getrange key2 0 4
    55. "nicho"
    56. # mget:指获取key的子字符串,若不存在刚返回nil
    57. 127.0.0.1:6379> mget key1 key2 key3 0 4
    58. 1) "test"
    59. 2) "nicholas"
    60. 3) "sasaki"
    61. 4) (nil)
    62. 5) (nil)
    63. # incr:对key的值作加加操作,返回新值
    64. 127.0.0.1:6379> set num 10
    65. OK
    66. 127.0.0.1:6379> get num
    67. "10"
    68. 127.0.0.1:6379> incr num
    69. (integer) 11
    70. 127.0.0.1:6379> incr num
    71. (integer) 12
    72. # incrby:同incr,加指定值,key值不存在会设置key,并认为原key值为0
    73. 127.0.0.1:6379> incrby num_ 20
    74. (integer) 20
    75. 127.0.0.1:6379> incrby num__ 6
    76. (integer) 6
    77. 127.0.0.1:6379> incrby num__ 6
    78. (integer) 12
    79. 127.0.0.1:6379> incrby num__ 6
    80. (integer) 18
    81. # decr:对key的值作减减操作,返回新值
    82. # decrby:同decr,减指定值,key值不存在会设置key,并认为原key值为0
    83. # append:给指定key的字符串追加value,返回新字符串值的长度
    84. 127.0.0.1:6379> set head redskirt
    85. OK
    86. 127.0.0.1:6379> append head @outlook.com
    87. (integer) 20
    88. 127.0.0.1:6379> get head
    89. "redskirt@outlook.com"
    90. # strlen:取指定key的value值的长度
    91. 127.0.0.1:6379> strlen head
    92. (integer) 20

    hashes:Redis hash是一个string类型的filed和value的映射表。它的添加、删除操作都是0(1)(平均)。hash特别合适用于存储对象。相比于将对象的每个字段存成单个string类型,将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象

    1. # hset:设置hash field为指定值,如果key不存在,刚先创建
    2. 127.0.0.1:6379> hset user:001 name nicholas
    3. (integer) 1
    4. 127.0.0.1:6379> hget user:001 name
    5. "nicholas"
    6. # hsetnx:设置hash field为指定值,如果key不存在刚先创建,如果存在返回0
    7. 127.0.0.1:6379> hsetnx user:002 name lamp
    8. (integer) 1
    9. 127.0.0.1:6379> hget user:002 name
    10. "lamp"
    11. 127.0.0.1:6379> hsetnx user:002 name lamp
    12. (integer) 0
    13. # hmset:同时设置hash的多个field
    14. 127.0.0.1:6379> hmset user:003 name nicholas age 20 gender m
    15. OK
    16. 127.0.0.1:6379> hget user:003 age
    17. "20"
    18. 127.0.0.1:6379> hget user:003 gender
    19. "m"
    20. # hget:获取hash field的值
    21. # hmget:获取全部指定的hash filed
    22. 127.0.0.1:6379> hmget user:003 name age gender
    23. 1) "nicholas"
    24. 2) "20"
    25. 3) "m"
    26. # hincrby:给指定的hash filed加上指定值
    27. 127.0.0.1:6379> hincrby user:003 age 3
    28. (integer) 23
    29. # gexists:判断指定filed是否存在
    30. 127.0.0.1:6379> hexists user:003 age
    31. (integer) 1
    32. 127.0.0.1:6379> hexists user:003 age_
    33. (integer) 0
    34. # hlen:返回指定hash的filed的数量
    35. 127.0.0.1:6379> hlen user:003
    36. (integer) 3
    37. # ldel:删除指定hash的filed
    38. 127.0.0.1:6379> hdel user:003 age
    39. (integer) 1
    40. 127.0.0.1:6379> hget user:003 age
    41. (nil)
    42. # hkeys:返回hash的所有filed
    43. 127.0.0.1:6379> hkeys user:003
    44. 1) "name"
    45. 2) "gender"
    46. # hgetall:获取某hash中全部的file及value
    47. 127.0.0.1:6379> hgetall user:003
    48. 1) "name"
    49. 2) "nicholas"
    50. 3) "gender"
    51. 4) "m"

    lists:List是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等,操作中key理解为链表的名字。Redis的list类型其实就是一个每个子元素都是string类型的双向链表。可以通过push、pop操作从链表的头部或者尾部添加删除元素,这样List既可作为栈,又可以作为队列。

    1. # lpush:在key对应list的头部添加字符串元素,模拟栈
    2. 127.0.0.1:6379> lpush list 1
    3. (integer) 1
    4. 127.0.0.1:6379> lpush list 2
    5. (integer) 2
    6. 127.0.0.1:6379> lpush list 3
    7. (integer) 3
    8. 127.0.0.1:6379> lrange list 0 -1
    9. 1) "3"
    10. 2) "2"
    11. 3) "1"
    12. # rpush:在key对应list的尾部添加字符串元素,模拟队列
    13. 127.0.0.1:6379> lpush list_ 1
    14. (integer) 1
    15. 127.0.0.1:6379> lpush list_ 2
    16. (integer) 2
    17. 127.0.0.1:6379> lpush list_ 3
    18. (integer) 3
    19. 127.0.0.1:6379> lrange list_ 0 -1
    20. 1) "1"
    21. 2) "2"
    22. 3) "3"
    23. # linsert:在key对应的list的特定位置前或后添加字符串
    24. 127.0.0.1:6379> lpush list3 1
    25. (integer) 1
    26. 127.0.0.1:6379> lpush list3 2
    27. (integer) 2
    28. 127.0.0.1:6379> lrange list3 0 -1
    29. 1) "2"
    30. 2) "1"
    31. 127.0.0.1:6379> linsert list3 before 1 3
    32. (integer) 3
    33. 127.0.0.1:6379> lrange list3 0 -1
    34. 1) "2"
    35. 2) "3"
    36. 3) "1"
    37. # lset:设置List中指定下标的元素值
    38. 127.0.0.1:6379> lrange list3 0 -1
    39. 1) "2"
    40. 2) "3"
    41. 3) "1"
    42. 127.0.0.1:6379> lset list3 0 4
    43. OK
    44. 127.0.0.1:6379> lrange list3 0 -1
    45. 1) "4"
    46. 2) "3"
    47. 3) "1"
    48. # lrem:从key对应的List中删除n个和value相同的元素。(n<0从尾删除,n=0全部删除)
    49. 127.0.0.1:6379> lrange list3 0 -1
    50. 1) "4"
    51. 2) "3"
    52. 3) "1"
    53. 127.0.0.1:6379> lrem list3 1 4
    54. (integer) 1
    55. 127.0.0.1:6379> lrange list3 0 -1
    56. 1) "3"
    57. 2) "1"
    58. 127.0.0.1:6379> lpush list3 5
    59. (integer) 3
    60. 127.0.0.1:6379> lpush list3 5
    61. (integer) 4
    62. 127.0.0.1:6379> lpush list3 5
    63. (integer) 5
    64. 127.0.0.1:6379> lrange list3 0 -1
    65. 1) "5"
    66. 2) "5"
    67. 3) "5"
    68. 4) "3"
    69. 5) "1"
    70. 127.0.0.1:6379> lrem list3 0 5
    71. (integer) 3
    72. 127.0.0.1:6379> lrange list3 0 -1
    73. 1) "3"
    74. 2) "1"
    75. # ltrim:保留指定key的值范围内的数据
    76. 127.0.0.1:6379> lpush list5 1 2 3 4 5 6
    77. (integer) 6
    78. 127.0.0.1:6379> lrange list5 0 -1
    79. 1) "6"
    80. 2) "5"
    81. 3) "4"
    82. 4) "3"
    83. 5) "2"
    84. 6) "1"
    85. 127.0.0.1:6379> ltrim list5 0 3
    86. OK
    87. 127.0.0.1:6379> lrange list5 0 -1
    88. 1) "6"
    89. 2) "5"
    90. 3) "4"
    91. 4) "3"
    92. # lpop:从List的头部删除元素,并返回删除元素
    93. 127.0.0.1:6379> lrange list5 0 -1
    94. 1) "6"
    95. 2) "5"
    96. 3) "4"
    97. 4) "3"
    98. 127.0.0.1:6379> lpop list5
    99. "6"
    100. 127.0.0.1:6379> lrange list5 0 -1
    101. 1) "5"
    102. 2) "4"
    103. 3) "3"
    104. # rpop:从List的尾部删除元素,并返回删除元素
    105. 127.0.0.1:6379> rpop list5
    106. "3"
    107. 127.0.0.1:6379> lrange list5 0 -1
    108. 1) "5"
    109. 2) "4"
    110. # rpoplpush:从第一个List的尾部移除元素并添加到第二个List的头部
    111. 127.0.0.1:6379> rpush list9 1 2
    112. (integer) 2
    113. 127.0.0.1:6379> rpush list10 1 2
    114. (integer) 2
    115. 127.0.0.1:6379> lrange list9 0 -1
    116. 1) "1"
    117. 2) "2"
    118. 127.0.0.1:6379> lrange list10 0 -1
    119. 1) "1"
    120. 2) "2"
    121. 127.0.0.1:6379> rpoplpush list9 list10
    122. "2"
    123. 127.0.0.1:6379> lrange list9 0 -1
    124. 1) "1"
    125. 127.0.0.1:6379> lrange list10 0 -1
    126. 1) "2"
    127. 2) "1"
    128. 3) "2"
    129. # lindex:返回名称为key的List中的index位置的元素
    130. 127.0.0.1:6379> lrange list10 0 -1
    131. 1) "2"
    132. 2) "1"
    133. 3) "2"
    134. 127.0.0.1:6379> lindex list10 0
    135. "2"
    136. 127.0.0.1:6379> lindex list10 1
    137. "1"
    138. # llen:返回key对应的List的长度
    139. 127.0.0.1:6379> llen list10
    140. (integer) 3

    sets:Set是string类型的无序集合,通过hash table实现,添加、删除和查找的复杂度都是0(1),可以对集合取并集、交集、差集。通过这些操作可以实现SNS好友推荐和Blog的Tag功能。

    1. # sadd:向名称为key的Set中添加元素
    2. 127.0.0.1:6379> sadd set1 1
    3. (integer) 1
    4. 127.0.0.1:6379> sadd set1 2
    5. (integer) 1
    6. 127.0.0.1:6379> sadd set1 2
    7. (integer) 0
    8. 127.0.0.1:6379> smembers set1
    9. 1) "1"
    10. 2) "2"
    11. # srem:删除名称为key的Set中的元素
    12. 127.0.0.1:6379> srem set1 2
    13. (integer) 1
    14. 127.0.0.1:6379> srem set1 2
    15. (integer) 0
    16. 127.0.0.1:6379> smembers set1
    17. 1) "1"
    18. # spop:随机返回并删除名称为key的Set中的一个元素
    19. 127.0.0.1:6379> smembers set2
    20. 1) "1"
    21. 2) "2"
    22. 3) "3"
    23. 4) "4"
    24. 5) "5"
    25. 127.0.0.1:6379> spop set2
    26. "3"
    27. 127.0.0.1:6379> spop set2
    28. "1"
    29. 127.0.0.1:6379> spop set2
    30. "5"
    31. 127.0.0.1:6379> smembers set2
    32. 1) "2"
    33. 2) "4"
    34. # sdiff:返回所有给定key与第一个key的差集
    35. 127.0.0.1:6379> smembers set2
    36. 1) "2"
    37. 2) "4"
    38. 127.0.0.1:6379> smembers set3
    39. 1) "1"
    40. 2) "2"
    41. 3) "3"
    42. 4) "4"
    43. 127.0.0.1:6379> sdiff set2 set3
    44. (empty list or set)
    45. 127.0.0.1:6379> sdiff set3 set2
    46. 1) "1"
    47. 2) "3"
    48. # sinter:返回所有给定key的交集
    49. 127.0.0.1:6379> sinter set2 set3
    50. 1) "2"
    51. 2) "4"
    52. # sinterstore:返回所有给定key的交集,并将结果存为另一个key
    53. 127.0.0.1:6379> smembers set2
    54. 1) "2"
    55. 2) "4"
    56. 127.0.0.1:6379> smembers set3
    57. 1) "1"
    58. 2) "2"
    59. 3) "3"
    60. 4) "4"
    61. 127.0.0.1:6379> sinterstore set4 set2 set3
    62. (integer) 2
    63. 127.0.0.1:6379> smembers set4
    64. 1) "2"
    65. 2) "4"
    66. # sunion:返回所有给定的key的并集
    67. 127.0.0.1:6379> sunion set2 set3
    68. 1) "1"
    69. 2) "2"
    70. 3) "3"
    71. 4) "4"
    72. # sunionstore:返回所有给定key的并集,并将结果存为另一个key
    73. 127.0.0.1:6379> sunionstore set5 set2 set3
    74. (integer) 4
    75. 127.0.0.1:6379> smembers set5
    76. 1) "1"
    77. 2) "2"
    78. 3) "3"
    79. 4) "4"
    80. # smove:从第一个key对应的Set中移除member并添加到第二个对应的Set中
    81. 127.0.0.1:6379> smove set2 set3 2
    82. (integer) 1
    83. 127.0.0.1:6379> smembers set2
    84. 1) "4"
    85. 127.0.0.1:6379> smembers set3
    86. 1) "1"
    87. 2) "2"
    88. 3) "3"
    89. 4) "4"
    90. # scard:返回名称为key的Set的元素个数
    91. 127.0.0.1:6379> scard set3
    92. (integer) 4
    93. # sismember:判断member是否为名称为key的Set的元素
    94. 127.0.0.1:6379> scard set3
    95. (integer) 4
    96. 127.0.0.1:6379> sismember set3 1
    97. (integer) 1
    98. 127.0.0.1:6379> sismember set3 5
    99. (integer) 0
    100. # srandmember:随机返回名称为key的Set的一个元素,但不删除元素
    101. 127.0.0.1:6379> srandmember set3
    102. "2"
    103. 127.0.0.1:6379> srandmember set3
    104. "1"
    105. 127.0.0.1:6379> srandmember set3
    106. "3"
    107. 127.0.0.1:6379> smembers set3
    108. 1) "1"
    109. 2) "2"
    110. 3) "3"
    111. 4) "4"

    sorted set:sorted set在set的基础上增加了顺序属性,在添加元素时可以指定顺序,每次指定后,zset会自动重新按新的值调整顺序。可以理解为有两列的Mysql表,一列存Value,一列存顺序。操作中key理解为zset的名字。

    1. # zadd:向名称为key的Zset中添加元素member,score用于排序。如果该元素存在则更新其顺序。
    2. 127.0.0.1:6379> zadd zset1 1 one
    3. (integer) 1
    4. 127.0.0.1:6379> zadd zset1 2 two
    5. (integer) 1
    6. 127.0.0.1:6379> zadd zset1 3 two
    7. (integer) 0
    8. 127.0.0.1:6379> zadd zset1 4 four
    9. (integer) 1
    10. 127.0.0.1:6379> zrange zset1 0 -1 withscores
    11. 1) "one"
    12. 2) "1"
    13. 3) "two"
    14. 4) "3"
    15. 5) "four"
    16. 6) "4"
    17. # zrem:删除名称为key的Zset中的元素member
    18. 127.0.0.1:6379> zrem zset1 two
    19. (integer) 1
    20. 127.0.0.1:6379> zrem zset1 two
    21. (integer) 0
    22. 127.0.0.1:6379> zrange zset1 0 -1 withscores
    23. 1) "one"
    24. 2) "1"
    25. 3) "four"
    26. 4) "4"
    27. # zincrby:如果在名称为key的Zset中已经存在元素member,则该元素的score增加incrememt,否则向该集合中添加该元素,其中score的值为increment
    28. 127.0.0.1:6379> zincrby zset1 2 one
    29. "3"
    30. 127.0.0.1:6379> zincrby zset1 4 five
    31. "4"
    32. 127.0.0.1:6379> zrange zset1 0 -1 withscores
    33. 1) "one"
    34. 2) "3"
    35. 3) "five"
    36. 4) "4"
    37. 5) "four"
    38. 6) "4"
    39. # zrank:返回名称为key的Zset中memmber的元素排名(按score升序排序),即下标
    40. 127.0.0.1:6379> zrank zset1 one
    41. (integer) 0
    42. 127.0.0.1:6379> zrank zset1 five
    43. (integer) 1
    44. 127.0.0.1:6379> zrank zset1 four
    45. (integer) 2
    46. # zrevrank:返回名称为key的Zset中memmber的元素排名(按score降序排序),即下标
    47. 127.0.0.1:6379> zrevrank zset1 one
    48. (integer) 2
    49. 127.0.0.1:6379> zrevrank zset1 five
    50. (integer) 1
    51. 127.0.0.1:6379> zrevrank zset1 four
    52. (integer) 0
    53. # zrevrange:返回名称为key的Zset(按score降序)中的index从start到end的所有元素
    54. 127.0.0.1:6379> zrevrange zset2 0 -1 withscores
    55. 1) "four"
    56. 2) "4"
    57. 3) "three"
    58. 4) "3"
    59. 5) "two"
    60. 6) "2"
    61. 7) "one"
    62. 8) "1"
    63. # zrangebyscore:返回集合中score在给定区间的元素
    64. 127.0.0.1:6379> zrangebyscore zset2 2 4 withscores
    65. 1) "two"
    66. 2) "2"
    67. 3) "three"
    68. 4) "3"
    69. 5) "four"
    70. 6) "4"
    71. # zcount:返回集合中score在给定区间的数量
    72. 127.0.0.1:6379> zcount zset2 1 4
    73. (integer) 4
    74. # zcard:返回集合中的元素个数
    75. 127.0.0.1:6379> zcard zset2
    76. (integer) 4
    77. # zremrangebyrank:依据索引删除集合中排名在给定区间的元素
    78. 127.0.0.1:6379> zremrangebyrank zset2 1 3
    79. (integer) 3
    80. 127.0.0.1:6379> zrange zset2 0 -1 withscores
    81. 1) "one"
    82. 2) "1"
    83. # zremrangebyscore:依据顺序删除集合中排名在给定区间的元素
    84. 127.0.0.1:6379> zrange zset3 0 -1 withscores
    85. 1) "one"
    86. 2) "1"
    87. 3) "two"
    88. 4) "2"
    89. 5) "three"
    90. 6) "3"
    91. 7) "four"
    92. 8) "4"
    93. 9) "five"
    94. 10) "5"
    95. 127.0.0.1:6379> zremrangebyscore zset3 1 3
    96. (integer) 3
    97. 127.0.0.1:6379> zrange zset3 0 -1 withscores
    98. 1) "four"
    99. 2) "4"
    100. 3) "five"
    101. 4) "5"
  2. Redis常用命令

    1)键值相关命令

    1. # keys:返回满足给定pattern的所有key
    2. 127.0.0.1:6379> keys *
    3. 1) "num__"
    4. 2) "num"
    5. 3) "head"
    6. 4) "set4"
    7. 5) "zset1"
    8. 6) "hello"
    9. 7) "zset3"
    10. 8) "list3"
    11. 9) "list4"
    12. 10) "set2"
    13. 127.0.0.1:6379> keys set*
    14. 1) "set4"
    15. 2) "set2"
    16. 3) "set1"
    17. 4) "set3"
    18. 5) "set5"
    19. # exists:确认一个key是否存在
    20. 127.0.0.1:6379> exists zset
    21. (integer) 0
    22. 127.0.0.1:6379> exists zset1
    23. (integer) 1
    24. # del:删除一个key
    25. 127.0.0.1:6379> del set3
    26. (integer) 1
    27. 127.0.0.1:6379> exists set3
    28. (integer) 0
    29. # expire:设置一个key的过期时间
    30. 127.0.0.1:6379> expire set1 10
    31. (integer) 1
    32. 127.0.0.1:6379> ttl set1
    33. (integer) -2
    34. # move:移动key到指定数据库
    35. 127.0.0.1:6379> exists set5
    36. (integer) 1
    37. 127.0.0.1:6379> move set5 1
    38. (integer) 1
    39. 127.0.0.1:6379> exists set5
    40. (integer) 0
    41. 127.0.0.1:6379> select 1
    42. OK
    43. 127.0.0.1:6379[1]> exists set5
    44. (integer) 1
    45. # persist:移除给定key的过期时间
    46. 127.0.0.1:6379[1]> expire set5 300
    47. (integer) 1
    48. 127.0.0.1:6379[1]> ttl set5
    49. (integer) 294
    50. 127.0.0.1:6379[1]> persist set5
    51. (integer) 1
    52. 127.0.0.1:6379[1]> ttl set5
    53. (integer) -1
    54. # randomkey:随机返回key空间的一个key
    55. 127.0.0.1:6379> randomkey
    56. "list6"
    57. 127.0.0.1:6379> randomkey
    58. "key3"
    59. 127.0.0.1:6379> randomkey
    60. "list10"
    61. 127.0.0.1:6379> randomkey
    62. "head"
    63. # rename:重命名key
    64. 127.0.0.1:6379> rename key3 key30
    65. OK
    66. 127.0.0.1:6379> exists key3
    67. (integer) 0
    68. 127.0.0.1:6379> exists key30
    69. (integer) 1
    70. # type:返回值的类型
    71. 127.0.0.1:6379> type key30
    72. string
    73. 127.0.0.1:6379> type zset3
    74. zset

    2)服务器相关命令

    1. # ping:测试连接是否存活
    2. 127.0.0.1:6379> ping
    3. PONG
    4. # echo:在命令行打印内容
    5. 127.0.0.1:6379> echo honey
    6. "honey"
    7. # select:选择数据库。Redis数据库编号从0~15
    8. 127.0.0.1:6379> select 0
    9. OK
    10. 127.0.0.1:6379> select 1
    11. OK
    12. 127.0.0.1:6379[1]> keys *
    13. (empty list or set)
    14. # quit:退出连接
    15. # dbsize:返回当前数据库中key的数目
    16. 127.0.0.1:6379> dbsize
    17. (integer) 28
    18. # info:返回Redis服务器信息
    19. # config get:实时转存收到的请求
    20. 127.0.0.1:6379> config get dir
    21. 1) "dir"
    22. 2) "/usr/redis-3.0.6"
    23. 127.0.0.1:6379> config get *
    24. 1) "dbfilename"
    25. 2) "dump.rdb"
    26. 3) "requirepass"
    27. 4) ""
    28. 5) "masterauth"
    29. 6) ""
    30. 7) "unixsocket"
    31. 8) ""
    32. 9) "logfile"
    33. ...
    34. # flushdb:删除当前选择数据库中的所有key
    35. 127.0.0.1:6379> flushdb
    36. OK
    37. 127.0.0.1:6379> dbsize
    38. (integer) 0
    39. # flushall:删除所有数据库中的所有key
    40. 127.0.0.1:6379> flushall
    41. OK
  3. Redis高级实用特性

    • 安全性
    • 主从复制
    • 事务处理
    • 持久化机制
    • 发布订阅消息
    • 虚拟内存使用

    安全性:设置客户端连接后进行任何其他指定前需要使用的密码。
    警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解。

    1. [root@master ~]# vim /usr/redis-3.0.6/redis.conf
    2. ...
    3. requirepass honey
    4. [root@master ~]# pkill redis-server
    5. [root@master ~]# redis-server /usr/redis-3.0.6/redis.conf &
    6. # 进入Redis后用auth授权
    7. **127.0.0.1:6379> auth honey
    8. OK
    9. 127.0.0.1:6379> keys *
    10. (empty list or set)**
    11. # 或者登陆Redis时直接授权
    12. [root@master ~]# redis-cli -a honey

    主从复制:Redis主从复制配置和使用都非常简单。通过主从复制可以允许多个slave server拥有和master server相同的数据库副本。

    主从复制特点

    • master可以拥有多个slave
    • 多个slave可以连接同一个master外,还可以连接到其他slave
    • 主从复制不会阻塞master,在同步数据时,master可以继续处理client请求
    • 提高系统的伸缩性

    redis主从复制过程
    当配置好slave后,slave与master建立连接,然后发送sync命令。无论是第一次连接还是重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存。后台进程完成写文件后,master就发送文件给slave,slave将文件保存到硬盘上,再加载到内存中,接着master就会把缓存的命令转发给slave,后续master将收到的写命令发送给slave。如果master同时收到多个slave发来的同步连接命令,master只会启动一个进程来写数据库镜像,然后发送给所有的slave。

    配置主从服务器

    1. [root@slave01 ~]# cd /usr/redis-3.0.6/
    2. [root@slave01 redis-3.0.6]# vim redis.conf
    3. ...
    4. slaveof master 6379
    5. masterauth honey
    6. # 在主数据库中设置key
    7. [root@master ~]# redis-cli -a honey
    8. 127.0.0.1:6379> flushall
    9. 10025:M 26 Jan 15:35:50.769 * DB saved on disk
    10. OK
    11. 127.0.0.1:6379> set key testsync
    12. OK
    13. # 从数据库中会自动同步
    14. [root@slave01 redis-3.0.6]# redis-cli -a honey
    15. 127.0.0.1:6379> keys *
    16. 1) "key"
    17. 127.0.0.1:6379> get key
    18. "testsync"
    19. # info查看主从信息
    20. 127.0.0.1:6379> info
    21. ...
    22. # Replication
    23. role:slave
    24. master_host:master
    25. master_port:6379
    26. master_link_status:up
    27. master_last_io_seconds_ago:1
    28. master_sync_in_progress:0

    事务处理
    redis目前还是支持比较简单的事务处理,redis只能保证一个client发起的事务中的命令连续执行,而中间不会插入其他client的命令。
    一个client在一个连接中发起multi命令,这个链接会进入事务的上下文,该链接后续的命令不会被立即执行;而是先放到一个队列中,当执行exec命令后,redis会顺序执行队列中的命令。
    如果不行执行这个事务的话,可以用discard命令取消事物;队列中的命令会被取消,事务回滚掉。

    1. # multi开启一个事务
    2. 127.0.0.1:6379> multi
    3. OK
    4. 127.0.0.1:6379> set age 10
    5. QUEUED
    6. 127.0.0.1:6379> set age 100
    7. QUEUED
    8. 127.0.0.1:6379> exec
    9. 1) OK
    10. 2) OK
    11. 127.0.0.1:6379> get age
    12. "100"
    13. # discard取消一个事务
    14. 127.0.0.1:6379> get age
    15. "100"
    16. 127.0.0.1:6379> multi
    17. OK
    18. 127.0.0.1:6379> set age 10
    19. QUEUED
    20. 127.0.0.1:6379> set age 23
    21. QUEUED
    22. 127.0.0.1:6379> discard
    23. OK
    24. 127.0.0.1:6379> get age
    25. "100"
    26. # Redis只支持较简单的事务,事务过程中若有异常,整个事务不会回滚
    27. 127.0.0.1:6379> multi
    28. OK
    29. 127.0.0.1:6379> incr age
    30. QUEUED
    31. 127.0.0.1:6379> set name honey
    32. QUEUED
    33. 127.0.0.1:6379> incr name
    34. QUEUED
    35. 127.0.0.1:6379> exec
    36. 1) (integer) 101
    37. 2) OK
    38. 3) (error) ERR value is not an integer or out of range
    39. 127.0.0.1:6379> get age
    40. "101"

    Redis乐观锁的复杂事务
    乐观锁大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个“version”字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此Version+1。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

    1. # 乐观锁实例:对于一个key为name,我们开2个session对这个key进行赋值
    2. # session1中
    3. 127.0.0.1:6379> set name honey
    4. OK
    5. 127.0.0.1:6379> get name
    6. "honey"
    7. 127.0.0.1:6379> watch name
    8. OK
    9. 127.0.0.1:6379> multi
    10. OK
    11. 127.0.0.1:6379> set name honey_
    12. QUEUED
    13. # session2中
    14. 127.0.0.1:6379> set name nicholas
    15. OK
    16. 127.0.0.1:6379> get name
    17. "nicholas"
    18. # 返回session1提交事务
    19. 127.0.0.1:6379> exec
    20. (nil)
    21. 127.0.0.1:6379> get name
    22. "nicholas"

    watch命令会监视给定的key,当exec的时候如果该key在watch后发生过变化的话,则整个事物就会失败;也可以调用watch对多个key进行监视,这样就可以对多个key加乐观锁了。注意watch指定的key只对整个连接有效的,事务也是如此;若连接断开,监视会自动删除。

    悲观锁正如其名,具有强烈的独占和排他特性。它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。

    持久化机制
    redis持久化方式有两种:
    1)snapshotting,默认方式
    默认redis是会以快照的形式将数据持久化到磁盘的(一个二进制文件,dump.rdb,这个文件名字可以指定),在配置文件(redis.conf)中的格式是:save N M表示在N秒之内,redis至少发生M次修改则redis抓快照到磁盘。当然我们也可以手动执行save或者bgsave(异步)做快照。

    1. # Redis会把数据持久化到dump.rdb文件中
    2. [root@master redis-3.0.6]# ll dump.rdb
    3. -rw-r--r--. 1 root root 18 Jan 26 14:12 dump.rdb

    2)aof(Append-only file)方式
    filesnapshotting方法在redis异常死掉时,最近的数据会丢失(丢失数据的多少视你save策略的配置),所以这是它最大的缺点,当业务量很大时,丢失的数据是很多的。Append-only方法可以做到全部数据不丢失,但redis的性能就要差些。AOF就可以做到全程持久化,只需要在配置文件中开启(默认是no),appendonly yes开启AOF之后,redis每执行一个修改数据的命令,都会把它添加到aof文件中,当redis重启时,将会读取AOF文件进行“重放”以恢复到redis关闭前的最后时刻。
    AOF文件刷新的方式,有三种,在redis.conf参考配置参数appendfsync:
    appendfsync always每提交一个修改命令都调用fsync刷新到AOF文件,非常非常慢,但也非常安全;
    appendfsync everysec每秒钟都调用fsync刷新到AOF文件,很快,但可能会丢失一秒以内的数据;
    appendfsync no依靠OS进行刷新,redis不主动刷新AOF,这样最快,但安全性就差。默认并推荐每秒刷新,这样在速度和安全上都做到了兼顾。

    消息发布订阅(pub/sub)
    消息发布订阅是一种消息通信模式,主要的目的是解耦消息发布者和消息订阅者之间的耦合,这点和设计模式中的观察者模式比较相似。pub /sub不仅仅解决发布者和订阅者直接代码级别耦合也解决两者在物理部署上的耦合。
    redis作为一个pub/sub server,在订阅者和发布者之间起到了消息路由的功能。订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型,redis将消息类型称为通道(channel)。当发布者通过publish命令向redis server发送特定类型的消息时。订阅该消息类型的全部client都会收到此消息。这里消息的传递是多对多的。一个client可以订阅多个 channel,也可以向多个channel发送消息。

    1. # session1
    2. 127.0.0.1:6379> subscribe tv1
    3. Reading messages... (press Ctrl-C to quit)
    4. 1) "subscribe"
    5. 2) "tv1"
    6. 3) (integer) 1
    7. 1) "message"
    8. 2) "tv1"
    9. 3) "message1"
    10. 1) "message"
    11. 2) "tv1"
    12. 3) "hello....."
    13. # session2
    14. 127.0.0.1:6379> subscribe tv1 tv2
    15. Reading messages... (press Ctrl-C to quit)
    16. 1) "subscribe"
    17. 2) "tv1"
    18. 3) (integer) 1
    19. 1) "subscribe"
    20. 2) "tv2"
    21. 3) (integer) 2
    22. 1) "message"
    23. 2) "tv1"
    24. 3) "message1"
    25. 1) "message"
    26. 2) "tv1"
    27. 3) "hello....."
    28. # session3
    29. 127.0.0.1:6379> publish tv1 message1
    30. (integer) 2
    31. 127.0.0.1:6379> publish tv1 hello.....
    32. (integer) 2
    33. 127.0.0.1:6379> publish tv2 hello.....
    34. (integer) 1

    虚拟内存
    Redis的虚拟内存与os的虚拟内存不同,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的 内存空间用于其他需要访问的数据。尤其是对于redis这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个redis server外。另外的能够提高数据库容量的办法就是使用vm把那些不经常访问的数据交换的磁盘上。如果我们的存储的数据总是有少部分数据被经常访问,大 部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃。当少量数据被经常访问时,使用vm不但能提高单台redis server数据库的容量,而且也不会对性能造成太多影响。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注