redis缓存,rabbitMQ队列

本文介绍了Redis缓存数据库和RabbitMQ消息队列的使用。Redis作为NoSQL数据库,提供了丰富的数据类型和操作,如String、List、Set等,并支持原子操作和发布订阅功能。RabbitMQ则是工作队列模型,支持消息持久化、公平分发和选择性接收。文中还探讨了何时选择关系型数据库与NoSQL数据库,并给出了Redis性能测试结果。
摘要由CSDN通过智能技术生成

缓存数据库介绍

 NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库,随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。

NoSQL数据库的四大分类

键值(Key-Value)存储数据库

这一类数据库主要会使用到一个 哈希表,这个表中有一个特定的键和一个指针指向特定的数据。Key/value模型对于IT系统来说的优势在于简单、易部署。但是如果 DBA只对部分值进行查询或更新的时候,Key/value就显得效率低下了。[3]   举例如:Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB.
 
列存储数据库。
这部分数据库通常是用来应对分布式存储的海量数据。键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。如:Cassandra, HBase, Riak.
 
文档型数据库
文档型数据库的灵感是来自于Lotus Notes办公软件的,而且它同第一种键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高。如:CouchDB, MongoDb. 国内也有文档型数据库SequoiaDB,已经开源。
 
图形(Graph)数据库
图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。[2]   如:Neo4J, InfoGrid, Infinite Graph.
因此,我们总结NoSQL数据库在以下的这几种情况下比较适用:1、数据模型比较简单;2、需要灵活性更强的IT系统;3、对数据库性能要求较高;4、不需要高度的数据一致性;5、对于给定key,比较容易映射复杂值的环境。
 
NoSQL数据库的四大分类表格分析
分类 Examples举例 典型应用场景 数据模型 优点 缺点
键值(key-value)[3]  Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。[3]  Key 指向 Value 的键值对,通常用hash table来实现[3]  查找速度快 数据无结构化,通常只被当作字符串或者二进制数据[3] 
列存储数据库[3]  Cassandra, HBase, Riak 分布式的文件系统 以列簇式存储,将同一列数据存在一起 查找速度快,可扩展性强,更容易进行分布式扩展 功能相对局限
文档型数据库[3]  CouchDB, MongoDb Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) Key-Value对应的键值对,Value为结构化数据 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 查询性能不高,而且缺乏统一的查询语法。
图形(Graph)数据库[3]  Neo4J, InfoGrid, Infinite Graph 社交网络,推荐系统等。专注于构建关系图谱 图结构 利用图结构相关算法。比如最短路径寻址,N度关系查找等 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。[3] 

 

 

 

redis

介绍

redis是业界主流的key-value nosql 数据库之一。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis优点
  • 异常快速 : Redis是非常快的,每秒可以执行大约110000设置操作,81000个/每秒的读取操作。

  • 支持丰富的数据类型 : Redis支持最大多数开发人员已经知道如列表,集合,可排序集合,哈希等数据类型。

    这使得在应用中很容易解决的各种问题,因为我们知道哪些问题处理使用哪种数据类型更好解决。
  • 操作都是原子的 : 所有 Redis 的操作都是原子,从而确保当两个客户同时访问 Redis 服务器得到的是更新后的值(最新值)。

  • MultiUtility工具:Redis是一个多功能实用工具,可以在很多如:缓存,消息传递队列中使用(Redis原生支持发布/订阅),在应用程序中,如:Web应用程序会话,网站页面点击数等任何短暂的数据;
安装Redis环境
要在 Ubuntu 上安装 Redis,打开终端,然后输入以下命令:
$sudo apt-get update
$sudo apt-get install redis-server
这将在您的计算机上安装Redis

启动 Redis

$redis-server

查看 redis 是否还在运行

$redis-cli
这将打开一个 Redis 提示符,如下图所示:
redis 127.0.0.1:6379>
在上面的提示信息中:127.0.0.1 是本机的IP地址,6379是 Redis 服务器运行的端口。现在输入 PING 命令,如下图所示:
redis 127.0.0.1:6379> ping
PONG
这说明现在你已经成功地在计算机上安装了 Redis。
 
Python操作Redis
1
2
3
4
5
6
7
sudo pip install redis
or
sudo easy_install redis
or
源码安装
  
详见:https: / / github.com / WoLpH / redis - py

  

在Ubuntu上安装Redis桌面管理器

要在Ubuntu 上安装 Redis桌面管理,可以从 http://redisdesktop.com/download 下载包并安装它。

Redis 桌面管理器会给你用户界面来管理 Redis 键和数据。
 
 

Redis API使用

redis-py 的API的使用可以分类为:

  • 连接方式
  • 连接池
  • 操作
    • String 操作
    • Hash 操作
    • List 操作
    • Set 操作
    • Sort Set 操作
  • 管道
  • 发布订阅

 

连接方式

1、操作模式

redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。

1
2
3
4
5
import  redis
  
=  redis.Redis(host = '10.211.55.4' , port = 6379 )
r. set ( 'foo' 'Bar' )
print  r.get( 'foo' )

 

2、连接池

redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

 

操作

 

1. String操作

redis中的String在在内存中按照一个name对应一个value来存储。如图:

set(name, value, ex=None, px=None, nx=False, xx=False)

1
2
3
4
5
6
在Redis中设置值,默认,不存在则创建,存在则修改
参数:
      ex,过期时间(秒)
      px,过期时间(毫秒)
      nx,如果设置为True,则只有name不存在时,当前set操作才执行
      xx,如果设置为True,则只有name存在时,岗前set操作才执行
# EX 和 PX 可以同时出现,但后面给出的选项会覆盖前面给出的选项

redis 127.0.0.1:6379> SET key "value" EX 1000 PX 5000000
OK

redis 127.0.0.1:6379> TTL key
(integer) 4993  # 这是 PX 参数设置的值

redis 127.0.0.1:6379> SET another-key "value" PX 5000000 EX 1000
OK

redis 127.0.0.1:6379> TTL another-key
(integer) 997   # 这是 EX 参数设置的值
get(name)

返回 key 所关联的字符串值。

如果 key 不存在那么返回特殊值 nil 。


setnx (name, value)
将  key  的值设为  value  ,当且仅当  key  不存在。

若给定的 key 已经存在,则 SETNX 不做任何动作。

redis> EXISTS job                # job 不存在
(integer) 0

redis> SETNX job "programmer"    # job 设置成功
(integer) 1

redis> SETNX job "code-farmer"   # 尝试覆盖 job ,失败
(integer) 0

redis> GET job                   # 没有被覆盖
"programmer"
setex(name, time,value)

将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。

如果 key 已经存在, SETEX 命令将覆写旧值。

# key 已经存在时,SETEX 覆盖旧值

redis> SET cd "timeless"
OK

redis> SETEX cd 3000 "goodbye my love"
OK
psetex (name, time_ms, value)
这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
redis> PSETEX mykey 1000 "Hello"
OK

redis> PTTL mykey
(integer) 999

redis> GET mykey
"Hello"

mset(*args, **kwargs)

批量设置值
MSET key value [key value ...]

同时设置一个或多个 key-value 对。

redis> MSET date "2012.3.30" time "11:00 a.m." weather "sunny"
OK

redis> MGET date time weather
1) "2012.3.30"
2) "11:00 a.m."
3) "sunny"
mget(keys, *args)
返回所有(一个或多个)给定 key 的值。
redis> MGET redis mongodb
getrange(key, start, end)

返回 key 中字符串值的子字符串,字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。

负数偏移量表示从字符串最后开始计数, -1 表示最后一个字符, -2 表示倒数第二个,以此类推

redis> SET greeting "hello, my friend"
OK

redis> GETRANGE greeting 0 4          # 返回索引0-4的字符,包括4。
"hello"

redis> GETRANGE greeting -1 -5        # 不支持回绕操作
""

redis> GETRANGE greeting -3 -1        # 负数索引
"end"

redis> GETRANGE greeting 0 -1         # 从第一个到最后一个
"hello, my friend"

redis> GETRANGE greeting 0 1008611    # 值域范围不超过实际字符串,超过部分自动被符略
"hello, my friend"
setrange(name, offset, value)
1
2
3
4
# 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
# 参数:
     # offset,字符串的索引,字节(一个汉字三个字节)
     # value,要设置的值


redis> SET greeting "hello world"
OK

redis> SETRANGE greeting 6 "Redis"
(integer) 11

redis> GET greeting
"hello Redis"


# 对空字符串/不存在的 key 进行 SETRANGE

redis> EXISTS empty_string
(integer) 0

redis> SETRANGE empty_string 5 "Redis!"   # 对不存在的 key 使用 SETRANGE
(integer) 11

redis> GET empty_string                   # 空白处被"\x00"填充
"\x00\x00\x00\x00\x00Redis!"
redis> SET greeting "hello world"
OK

redis> SETRANGE greeting 6 "Redis"
(integer) 11

redis> GET greeting
"hello Redis"


# 对空字符串/不存在的 key 进行 SETRANGE

redis> EXISTS empty_string
(integer) 0

redis> SETRANGE empty_string 5 "Redis!"   # 对不存在的 key 使用 SETRANGE
(integer) 11

redis> GET empty_string                   # 空白处被"\x00"填充
"\x00\x00\x00\x00\x00Redis!"
setbit(name, offset, value)
redis> SET greeting "hello world"
OK

redis> SETRANGE greeting 6 "Redis"
(integer) 11

redis> GET greeting
"hello Redis"


# 对空字符串/不存在的 key 进行 SETRANGE

redis> EXISTS empty_string
(integer) 0

redis> SETRANGE empty_string 5 "Redis!"   # 对不存在的 key 使用 SETRANGE
(integer) 11

redis> GET empty_string                   # 空白处被"\x00"填充
"\x00\x00\x00\x00\x00Redis!"
# 对name对应值的二进制表示的位进行操作
 
# 参数:
     # name,redis的name
     # offset,位的索引(将值变换成二进制后再进行索引)
     # value,值只能是 1 或 0
 
# 注:如果在Redis中有一个对应: n1 = "foo",
         那么字符串foo的二进制表示为: 01100110  01101111  01101111
     所以,如果执行 setbit( 'n1' 7 1 ),则就会将第 7 位设置为 1
         那么最终二进制则变成  01100111  01101111  01101111 ,即: "goo"
 
# 扩展,转换二进制表示:
 
     # source = "萨德"
     source  =  "foo"
 
     for  in  source:
         num  =  ord (i)
         print  bin (num).replace( 'b' ,'')
 
     特别的,如果source是汉字  "萨德" 怎么办?
     答:对于utf - 8 ,每一个汉字占  3  个字节,那么  "萨德"  则有  9 个字节
        对于汉字, for 循环时候会按照 字节 迭代,那么在迭代时,将每一个字节转换 十进制数,然后再将十进制数转换成二进制
         11100110  10101101  10100110  11100110  10110010  10011011  11101001  10111101  10010000
         - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                   

getbit(name, offset)

1
# 获取name对应的值的二进制表示中的某位的值 (0或1)
redis> SET greeting "hello world"
OK

redis> SETRANGE greeting 6 "Redis"
(integer) 11

redis> GET greeting
"hello Redis"


# 对空字符串/不存在的 key 进行 SETRANGE

redis> EXISTS empty_string
(integer) 0

redis> SETRANGE empty_string 5 "Redis!"   # 对不存在的 key 使用 SETRANGE
(integer) 11

redis> GET empty_string                   # 空白处被"\x00"填充
"\x00\x00\x00\x00\x00Redis!"

bitcount(key, start=None, end=None)

1
2
3
4
5
# 获取name对应的值的二进制表示中 1 的个数
# 参数:
     # key,Redis的name
     # start,位起始位置
     # end,位结束位置

strlen(name)

1
# 返回name对应值的字节长度(一个汉字3个字节)
# 获取字符串的长度

redis> SET mykey "Hello world"
OK

redis> STRLEN mykey
(integer) 11

incr(self, name, amount=1)

1
2
3
4
5
6
7
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
 
# 参数:
     # name,Redis的name
     # amount,自增数(必须是整数)
 
# 注:同incrby
redis> SET page_view 20
OK

redis> INCR page_view
(integer) 21

redis> GET page_view    # 数字值在 Redis 中以字符串的形式保存
"21"

incrbyfloat(self, name, amount=1.0)

1
2
3
4
5
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
 
# 参数:
     # name,Redis的name
     # amount,自增数(浮点型
redis> SET mykey 10.50
OK

redis> INCRBYFLOAT mykey 0.1
"10.6"

decr(self, name, amount=1)

1
2
3
4
5
# 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。
 
# 参数:
     # name,Redis的name
     # amount,自减数(整数)
redis> SET failure_times 10
OK

redis> DECR failure_times
(integer) 9

append(key, value)

1
2
3
4
5
# 在redis name对应的值后面追加内容
 
# 参数:
     key, redis的name
     value, 要追加的字符串
redis> EXISTS myphone               # 确保 myphone 不存在
(integer) 0

redis> APPEND myphone "nokia"       # 对不存在的 key 进行 APPEND ,等同于 SET myphone "nokia"
(integer) 5                         # 字符长度
2. Hash操作

hash表现形式上有些像pyhton中的dict,可以存储一组关联性较强的数据 , redis中Hash在内存中的存储格式如下图:  

hset(name, key, value)

1
2
3
4
5
6
7
8
9
# name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
 
# 参数:
     # name,redis的name
     # key,name对应的hash中的key
     # value,name对应的hash中的value
 
# 注:
     # hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加)
redis> HSET website google "www.g.cn"       # 设置一个新域
(integer) 1

redis> HSET website google "www.google.com" # 覆盖一个旧域
(integer) 0

hmset(name, mapping)

1
2
3
4
5
6
7
8
# 在name对应的hash中批量设置键值对
 
# 参数:
     # name,redis的name
     # mapping,字典,如:{'k1':'v1', 'k2': 'v2'}
 
# 如:
     # r.hmset('xx', {'k1':'v1', 'k2': 'v2'})
127.0.0.1:6379> hmset go k1 2 k2 3
OK
127.0.0.1:6379> hget go k1
"2"

hget(name,key)

1
# 在name对应的hash中获取根据key获取value

hmget(name, keys, *args)

1
2
3
4
5
6
7
8
9
10
11
# 在name对应的hash中获取多个key的值
 
# 参数:
     # name,reids对应的name
     # keys,要获取key集合,如:['k1', 'k2', 'k3']
     # *args,要获取的key,如:k1,k2,k3
 
# 如:
     # r.mget('xx', ['k1', 'k2'])
     # 或
     # print r.hmget('xx', 'k1', 'k2')
hmget go k1 k2

hgetall(name)

1
获取name对应 hash 的所有键值

hlen(name)

1
# 获取name对应的hash中键值对的个数

hkeys(name)

1
# 获取name对应的hash中所有的key的值

hvals(name)

1
# 获取name对应的hash中所有的value的值

hexists(name, key)

1
# 检查name对应的hash是否存在当前传入的key

hdel(name,*keys)

1
# 将name对应的hash中指定key的键值对删除

hincrby(name, key, amount=1)

1
2
3
4
5
# 自增name对应的hash中的指定key的值,不存在则创建key=amount
# 参数:
     # name,redis中的name
     # key, hash对应的key
     # amount,自增数(整数)

127.0.0.1:6379> hincrby count page 200 (integer) 200 127.0.0.1:6379> hget count page "200" 127.0.0.1:6379> hincrby count var 200 (integer) 200 127.0.0.1:6379> hget count var "200" 127.0.0.1:6379> hincrby count var -50 (integer) 150 127.0.0.1:6379> hget count var "150"

hincrbyfloat(name, key, amount=1.0)

1
2
3
4
5
6
7
8
# 自增name对应的hash中的指定key的值,不存在则创建key=amount
 
# 参数:
     # name,redis中的name
     # key, hash对应的key
     # amount,自增数(浮点数)
 
# 自增name对应的hash中的指定key的值,不存在则创建key=amount
# 值和增量都是普通小数
redis> HSET mykey field 10.50
(integer) 1
redis> HINCRBYFLOAT mykey field 0.1
"10.6"
# 值和增量都是指数符号
redis> HSET mykey field 5.0e3
(integer) 0
redis> HINCRBYFLOAT mykey field 2.0e2
"5200"
# 对不存在的键执行 HINCRBYFLOAT
redis> EXISTS price
(integer) 0
redis> HINCRBYFLOAT price milk 3.5
"3.5"
redis> HGETALL price
1) "milk"
2) "3.5"
# 对不存在的域进行 HINCRBYFLOAT
redis> HGETALL price
1) "milk"
2) "3.5"
redis> HINCRBYFLOAT price coffee 4.5   # 新增 coffee 域
"4.5"
redis> HGETALL price
1) "milk"
2) "3.5"
3) "coffee"
4) "4.5"
hscan(name, cursor=0, match=None, count=None)

1
2
3
4
5
6
7
8
9
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值