Infi-chu: http://www.cnblogs.com/Infi-chu/ NoSQL(NoSQL=Not Only SQL),中文意思是非關係型資料庫。 隨著互聯網Web2.0網站的興起,傳統的關係型資料庫在應付web2.0網站,特別是超大規模和高併發的SNS類型的web2.0純動態網站 ...
Infi-chu:
http://www.cnblogs.com/Infi-chu/
NoSQL(NoSQL=Not Only SQL),中文意思是非關係型資料庫。
隨著互聯網Web2.0網站的興起,傳統的關係型資料庫在應付web2.0網站,特別是超大規模和高併發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了很多難以剋服的問題,而非關係型的資料庫則由於其本身的特點得到了非常迅速的發展。
NoSQL的優點:
- 大數據量,高性能
- 靈活的數據模型
- 高可用
NoSQL的缺點:
- 沒有正式的官方支持,出錯之後後果十分可怕
- 並沒有一定的標準,各種產品參差不齊
NoSQL資料庫的四大分類:
- 鍵值存儲資料庫:主要使用一個哈希表,這個表中有一個特定的鍵和一個指針指向指定的數據,優點是簡單、易部署。缺點是在查詢和更新時的效率較低。如:Redis、Oracle BDB
- 列存儲資料庫:一般用來對應分散式存儲的海量數據,鍵依舊存在,但指向了多個列。如:Hbase(大數據存儲)、Cassandra
- 文檔型資料庫:與鍵值存儲相似,該類型的數據模型是版本化的文檔,半結構化的文檔以特定的格式存儲,比如JSON。文檔型資料庫可 以看作是鍵值資料庫的升級版,允許之間嵌套鍵值。而且文檔型資料庫比鍵值資料庫的查詢效率更高。如:CouchDB, MongoDb。
- 圖形資料庫:使用靈活的圖形模型,並能夠擴展到多個伺服器上。如InfoGrid、Neo4J、Infinite Graph。
對比:
Redis
redis是業界主流的key-value nosql 資料庫之一。和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在記憶體中。區別的是redis會周期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。
Redis的優點:
- 快速
- 豐富的數據類型
- 多用戶同時訪問得到的都是最新的數據
- 多功能實用的工具
Python操作Redis
pip install redis
有用的一些操作
ps -ef | grep redis 查看進程狀態 netstat -tulnp 查看埠號 redis -cli 本地連接Redis
Redis API(redis-py)使用可以分為5類:
- 連接方式
- 連接池
- 操作:String操作、Hash操作、List操作、Set操作、Sort Set操作
- 管道
- 發佈訂閱
一、連接方式
操作模式:
- 提供兩個類:Redis和StrictRedis用於實現rRedis的命令,StrictRedis用於實現大部分的官方命令,並使用官方的語法和命令,Redis是StrictRedis的子類,用於向後相容舊版本的redis-py
#import redis #a=redis.Redis(host='192.168.1.1',port=6379) #a.set('foo','Bar') #print(r.get('foo'))
二、連接池
Redis-py使用connection pool來管理一個redis server的所有連接,避免每次建立、釋放連接的開銷。
在預設情況下,每個Redis實例都會維護一個自己的連接池。可以直接建立一個連接池,然後作為參數Redis,這樣就可以實現多個Redis實例共用一個連接池。
三、操作
1.String操作:
在記憶體中按照一個name對應一個value來存儲,一 一對應的關係
#終端語法: #set name bob #存 #get name #取 #keys * #取出所有key值 #set name sam ex 3 #3秒後自動刪除
1.String操作: 在記憶體中按照一個name對應一個value來存儲,一 一對應的關係 #python語法: #set(name,value,ex=None,px=None,nx=False,xx=False) #在Redis中設置值,預設,不存在則創建,存在則修改 #參數: # ex:過期時間(秒) # px:過期時間(毫秒) # nx:如果設置為True,只有name不存在時,當前set才執行 # xx:如果設置為True,只有name存在時,當前set操作才執行 #setnx(name,value) #設置值,只有name不存在時,才執行 #setex(name,value,time) #設置值,time為過期時間(秒) #psetex(name,time_ms,value) #設置值,time_ms過期時間(毫秒) #mset(*args,**kwargs) #批量設置值 #例子:mset(n1='a',n2='b')或mget({'n1':'a','n2':'b'}) #get(name) #獲取值 #mget(keys,*args) #批量獲取 #例子:mget('a1','a2')或r.mget(['a1','a2']) #getset(name,value) #設置新的值,並且同時得到原來的值 #getrange(key,start,end) #獲取子序列(根據位元組獲取,開始位元組,結束位元組) #setrange(name,offset,value) #修改字元串內容,從指定位置開始向後替代,超出則為添加 #offset,字元串索引,位元組(1個漢字為3個位元組) #value,要設置的值 #setbit(name,offset,value) #對name對應的值的二進位表示的位進行操作 #name:name #offset:位的索引(將值變為二進位後再進行索引) #value:只能是0或1 #getbit(name,offset) #獲取name對應的值的二進位表示表示中的某位的值 #bitcount(key,start=None,end=None) #獲取name對應的值的二進位表示中1的個數 #strlen(name) #返回name對應值的位元組長度 #incr(self,name,amount=1) #自增,name對應的值,當name不存在時,則創建name=amount,否則自增 #amount為自增數 #incrbyfloat(self,name,amount=1.0) #浮點型 #decr(self,name,amount=1) #自減,name對應的值,當name不存在時,則創建name=amount,否則自減 #append(key,value) #在Redis中,name對應的值後面追加的內容 2.Hash操作 與python中的字典類似,可以存儲一組關聯性較強的數據,一對一組的關係,組中也有對應關係 #hset(name,key,value) #name對應的hash中設置一個鍵值對(有則修改,無則創建) #name:name #key:name對應的值中的鍵 #value:name對應的值中的值 #hmset(name,mapping) #在name對應的hash中批量設置鍵值對 #例子:r.hmset('a',{'b1':'q','b2':'w'}) #hget(name,key) #在name對應的組中,根據key獲取value #hmget(name,keys,*args) #在name對應的組中,獲取多個key的值 #hgetall(name) #獲取name對應的組中所有的鍵值 #hlen(name) #獲取name對應的組中鍵值對的個數 #hkeys(name) #獲取name對應的組中,所有的key的值 #hvals(name) #獲取name對應的組中,所有的value的值 #hexists(name,key) #檢查name對應的組中,是否存在當前傳入的key #hdel(name,*keys) #將name對應的組中,指定的key的鍵值對刪除 #hincrby(name,key,amount=1) #自增name對應的組中,指定key的值,不存在則創建key=amount #hincrbyfloat(name, key, amount=1.0) #浮點自增 #hscan(name,cursor=0,match=None,count=None) # 增量式迭代獲取,對於數據大的數據非常有用,hscan可以實現分片的獲取數據,並非一次性將數據全部獲取完,從而放置記憶體被撐爆 # 參數: # name,redis的name # cursor,游標(基於游標分批取獲取數據) # match,匹配指定key,預設None 表示所有的key # count,每次分片最少獲取個數,預設None表示採用Redis的預設分片個數 # 如: # 第一次:cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None) # 第二次:cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None) # ... # 直到返回值cursor的值為0時,表示數據已經通過分片獲取完畢 3.list操作 一個name對應一個list #lpush(name,values) #在name對應的list中添加元素,每個新的元素都添加到列表的最左邊 # rpush(name, values) 表示從右向左操作 #lpushx(name,value) #在name對應的list中添加元素,只有name已經存在時,值添加到列表的最左邊 # rpushx(name, value) 表示從右向左操作 #llen(name) #name對應的list元素個數 #linsert(name,where,refvalue,value) # 在name對應的列表的某一個值前或後插入一個新值 # 參數: # name,redis的name # where,BEFORE或AFTER # refvalue,標桿值,即:在它前後插入數據 # value,要插入的數據 #r.lrem(name,value,num) # 在name對應的list中刪除指定的值 # 參數: # name,redis的name # value,要刪除的值 # num, num=0,刪除列表中所有的指定值 # num=2,從前到後,刪除2個 # num=-2,從後向前,刪除2個 #lpop(name) # 在name對應的列表的左側獲取第一個元素併在列表中移除,返回值則是第一個元素 # rpop(name) 表示從右向左操作 #lindex(name, index) #在name對應的列表中根據索引獲取列表元素 #lrange(name, start, end) # 在name對應的列表分片獲取數據 # 參數: # name,redis的name # start,索引的起始位置 # end,索引結束位置 #ltrim(name, start, end) # 在name對應的列表中移除沒有在start-end索引之間的值 # 參數: # name,redis的name # start,索引的起始位置 # end,索引結束位置 #rpoplpush(src, dst) # 從一個列表取出最右邊的元素,同時將其添加至另一個列表的最左邊 # 參數: # src,要取數據的列表的name # dst,要添加數據的列表的name #blpop(keys, timeout) # 將多個列表排列,按照從左到右去pop對應列表的元素 # 參數: # keys,redis的name的集合 # timeout,超時時間,當元素所有列表的元素獲取完之後,阻塞等待列表內有數據的時間(秒), 0 表示永遠阻塞 # r.brpop(keys, timeout),從右向左獲取數據 #brpoplpush(src, dst, timeout=0) # 從一個列表的右側移除一個元素並將其添加到另一個列表的左側 # 參數: # src,取出並要移除元素的列表對應的name # dst,要插入元素的列表對應的name # timeout,當src對應的列表中沒有數據時,阻塞等待其有數據的超時時間(秒),0 表示永遠阻塞 4.set集合操作 set集合就是不允許重覆的列表 #sadd(name,values) # name對應的集合中添加元素 #scard(name) #獲取name對應的集合中元素個數 #sdiff(keys, *args) #在第一個name對應的集合中且不在其他name對應的集合的元素集合 #sdiffstore(dest, keys, *args) # 獲取第一個name對應的集合中且不在其他name對應的集合,再將其新加入到dest對應的集合中 #sinter(keys, *args) # 獲取多一個name對應集合的並集 #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對應的有序集合中添加元素 # 如: # zadd('zz', 'n1', 1, 'n2', 2) # 或 # zadd('zz', n1=11, n2=22) #zcard(name) # 獲取name對應的有序集合元素的數量 #zcount(name, min, max) # 獲取name對應的有序集合中分數 在 [min,max] 之間的個數 #zincrby(name, value, amount) # 自增name對應的有序集合的 name 對應的分數 #r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float) # 按照索引範圍獲取name對應的有序集合的元素 # 參數: # name,redis的name # start,有序集合索引起始位置(非分數) # end,有序集合索引結束位置(非分數) # desc,排序規則,預設按照分數從小到大排序 # withscores,是否獲取元素的分數,預設只獲取元素的值 # score_cast_func,對分數進行數據轉換的函數 # 更多: # 從大到小排序 # zrevrange(name, start, end, withscores=False, score_cast_func=float) # 按照分數範圍獲取name對應的有序集合的元素 # zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float) # 從大到小排序 # zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float) #zrank(name, value) # 獲取某個值在 name對應的有序集合中的排行(從 0 開始) # 更多: # zrevrank(name, value),從大到小排序 #zrem(name, values) # 刪除name對應的有序集合中值是values的成員 # 如:zrem('zz', ['s1', 's2']) #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進行操作 # aggregate的值為: SUM MIN MAX #zscan(name, cursor=0, match=None, count=None, score_cast_func=float) #zscan_iter(name, match=None, count=None,score_cast_func=float) # 同字元串相似,相較於字元串新增score_cast_func,用來對分數進行操作 5.其他操作 #delete(*names) # 根據刪除redis中的任意數據類型 #exists(name) # 檢測redis的name是否存在 #keys(pattern='*') # 根據模型獲取redis的name # 更多: # KEYS * 匹配資料庫中所有 key 。 # KEYS h?llo 匹配 hello , hallo 和 hxllo 等。 # KEYS h*llo 匹配 hllo 和 heeeeello 等。 # KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo #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) #scan_iter(match=None, count=None) # 同字元串操作,用於增量迭代獲取key
四、管道
redis-py預設在執行每次請求都會創建(連接池申請連接)和斷開(歸還連接池)一次連接操作,如果想要在一次請求中指定多個命令,則可以使用pipline實現一次請求指定多個命令,並且預設情況下一次pipline 是原子性操作。
五、發佈訂閱
讓多人可以知道某一個東西的內容