缓存数据库之redis
NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库,NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题
NoSQL数据库的四大分类
分类 | Examples举例 | 典型应用场景 | 数据模型 | 优点 | 缺点 |
---|---|---|---|---|---|
键值(key-value) | Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB | 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。 | Key 指向 Value 的键值对,通常用hash table来实现 | 查找速度快 | 数据无结构化,通常只被当作字符串或者二进制数据 |
列存储数据库 | Cassandra, HBase, Riak | 分布式的文件系统 | 以列簇式存储,将同一列数据存在一起 | 查找速度快,可扩展性强,更容易进行分布式扩展 | 功能相对局限 |
文档型数据库 | CouchDB, MongoDb | Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) | Key-Value对应的键值对,Value为结构化数据 | 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 | 查询性能不高,而且缺乏统一的查询语法。 |
图形(Graph)数据库 | Neo4J, InfoGrid, Infinite Graph | 社交网络,推荐系统等。专注于构建关系图谱 | 图结构 | 利用图结构相关算法。比如最短路径寻址,N度关系查找等 | 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。 |
redis是业界主流的key-value nosql 数据库之一。 键的类型是字符串且不能重复,值的类型可以分为五种字符串、哈希、列表、集合、有序集合。
安装Redis环境
$sudo apt-get update $sudo apt-get install redis-server
启动 Redis
$redis-server
查看 redis 是否还在运行
$redis-cli
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> ping PONG
import redis r = redis.Redis(host='10.211.55.4', port=6379) r.set('foo', 'Bar') print r.get('foo')
连接池,redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。
import redis pool = redis.ConnectionPool(host='192.168.0.110', port=6379) r = redis.Redis(connection_pool=pool) r.set('name', 'xmen') #添加 print (r.get('name')) #获取
管道,redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。
import redis pool = redis.ConnectionPool(host='192.168.0.110', port=6379) r = redis.Redis(connection_pool=pool) pipe = r.pipeline(transaction=True) r.set('name', 'zhangsan') r.set('name', 'lisi') pipe.execute()
发布和订阅
首先定义一个RedisHelper类,连接Redis,定义频道为monitor,定义发布(publish)及订阅(subscribe)方法
import redis class RedisHelper(object): def __init__(self): self.__conn = redis.Redis(host='192.168.0.110',port=6379)#连接Redis self.channel = 'monitor' #定义名称 def publish(self,msg):#定义发布方法 self.__conn.publish(self.channel,msg) return True def subscribe(self):#定义订阅方法 pub = self.__conn.pubsub() pub.subscribe(self.channel) pub.parse_response() return pub
发布者
from RedisHelper import RedisHelper obj = RedisHelper() obj.publish('hello')#发布
订阅者
from RedisHelper import RedisHelper obj = RedisHelper() redis_sub = obj.subscribe()#调用订阅方法 while True: msg= redis_sub.parse_response() print (msg)
基本操作
String操作 表现形式k1—>v1
set(name, value, ex=None, px=None, nx=False, xx=False)
setnx(name, value)
setex(name, value, time)#设置过期时间
psetex(name, time_ms, value)
mset(*args, **kwargs)#设置多个键值
get(name)#获取值
mget(keys, *args)#批量获取
getset(name, value)#设置新值并获取原来的值
getrange(key, start, end)# 获取子序列(根据字节获取,非字符)
setrange(name, offset, value)# 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
setbit(name, offset, value)# 对name对应值的二进制表示的位进行操作
getbit(name, offset)# 获取name对应的值的二进制表示中的某位的值 (0或1)
bitcount(key, start=None, end=None)# 获取name对应的值的二进制表示中 1 的个数
strlen(name)# 返回name对应值的字节长度(一个汉字3个字节)
incr(self, name, amount=1)# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
incrbyfloat(self, name, amount=1.0)# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
decr(self, name, amount=1)# 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。
append(key, value)# 在redis name对应的值后面追加内容
Hash操作,表现形式上有些像pyhton中的dict,可以存储一组关联性较强的数据 。k1——>{Kx—>Vx}
hset(name, key, value)# name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
hmset(name, mapping)# 在name对应的hash中批量设置键值对
hget(name,key)# 在name对应的hash中获取根据key获取value
hmget(name, keys, *args)# 在name对应的hash中获取多个key的值
hgetall(name)#获取name对应
hash
的所有键值
hlen(name)# 获取name对应的hash中键值对的个数
hkeys(name)# 获取name对应的hash中所有的key的值
hvals(name)# 获取name对应的hash中所有的value的值
hexists(name, key)# 检查name对应的hash是否存在当前传入的key
hdel(name,*keys)# 将name对应的hash中指定key的键值对删除
hincrby(name, key, amount=1)# 自增name对应的hash中的指定key的值,不存在则创建key=amount
hincrbyfloat(name, key, amount=1.0)# 自增name对应的hash中的指定key的值,不存在则创建key=amount
hscan_iter(name, match=None, count=None)# 利用yield封装hscan创建生成器,实现分批去redis中获取数据
List操作,redis中的List在在内存中按照一个name对应一个List来存储
lpush(name,values)# 在name对应的list中添加元素,每个新的元素都添加到列表的最左边
lpushx(name,value)# 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
llen(name)# name对应的list元素的个数
linsert(name, where, refvalue, value))# 在name对应的列表的某一个值前或后插入一个新值
lset(name, index, value)# 对name对应的list中的某一个索引位置重新赋值
lrem(name, value, num)# 在name对应的list中删除指定的值
lpop(name)# 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
lindex(name, index)#在name对应的列表中根据索引获取列表元素
lrange(name, start, end)# 在name对应的列表分片获取数据
ltrim(name, start, end)# 在name对应的列表中移除没有在start-end索引之间的值
rpoplpush(src, dst)# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
blpop(keys, timeout)# 将多个列表排列,按照从左到右去pop对应列表的元素
brpoplpush(src, dst, timeout=0)# 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
Set操作,Set集合就是不允许重复的列表
sadd(name,values)# name对应的集合中添加元素
scard(name)获取name对应的集合中元素个数
sdiff(keys, *args)在第一个name对应的集合中且不在其他name对应的集合的元素集合
sdiffstore(dest, keys, *args)# 获取第一个name对应的集合中且不在其他name对应的集合,再将其新加入到dest对应的集合中
sinter(keys, *args)# 该集合是所有给定集合的交集
sinterstore(dest, keys, *args)# 获取多一个name对应集合的并集,再讲其加入到dest对应的集合中
sismember(name, value)# 检查value是否是name对应的集合的成员
smembers(name)# 获取name对应的集合的所有成员
smove(src, dst, value)# 将某个成员从一个集合中移动到另外一个集合
spop(name)# 从集合的右侧(尾部)移除一个成员,并将其返回
srandmember(name, numbers)# 从name对应的集合中随机获取 numbers 个元素
srem(name, values)# 在name对应的集合中删除某些值
sunion(keys, *args)# 获取多一个name对应的集合的并集
sunionstore(dest,keys, *args)# 获取多一个name对应的集合的并集,并将结果保存到dest对应的集合中
sscan(name, cursor=0, match=None, count=None)
sscan_iter(name, match=None, count=None)# 同字符串的操作,用于增量迭代分批获取元素,避免内存消耗太大
有序集合,在集合的基础上,为每元素排序;元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。
zadd(name, *args, **kwargs)# 在name对应的有序集合中添加元素
zcard(name)# 获取name对应的有序集合元素的数量
zcount(name, min, max)# 获取name对应的有序集合中分数 在 [min,max] 之间的个数
zincrby(name, value, amount)# 自增name对应的有序集合的 name 对应的分数
zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)# 按照索引范围获取name对应的有序集合的元素
zrank(name, value)# 获取某个值在 name对应的有序集合中的排行(从 0 开始)
zrem(name, values)# 删除name对应的有序集合中值是values的成员
zremrangebyrank(name, min, max)# 根据排行范围删除
zremrangebyscore(name, min, max)# 根据分数范围删除
zscore(name, value)# 获取name对应有序集合中 value 对应的分数
zinterstore(dest, keys, aggregate=None)# 获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作,aggregate的值为: SUM MIN MAX
zunionstore(dest, keys, aggregate=None)# 获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
其他常用操作
delete(*names)# 根据删除redis中的任意数据类型
exists(name)# 检测redis的name是否存在
keys(pattern='*')# 根据模型获取redis的name
expire(name ,time)# 为某个redis的某个name设置超时时间
rename(src, dst)# 对redis的name重命名为
move(name, db))# 将redis的某个值移动到指定的db下
randomkey()# 随机获取一个redis的name(不删除)
type(name)# 获取name对应值的类型
scan(cursor=0, match=None, count=None)# 同字符串操作,用于增量迭代获取key
scan_iter(match=None, count=None)