八、redis 補充- 操作 - 增刪改查
對字典,重新設計結構,增刪改查。
hmset keys hget scan_iter hgetall
import redis import json conn = redis.Redis(host='140.143.227.206',port=6379,password='1234') """ -----> 第一版 { luffy_shopping_car:{ 6:{ 11:{ 'title':'21天入門到放棄', 'src':'xxx.png' }, 12:{ 'title':'21天入門到放棄', 'src':'xxx.png' } } } } -----> 第二版 { luffy_shopping_car_6_11:{ 'title':'21天入門到放棄', 'src':'xxx.png' }, luffy_shopping_car_6_12:{ 'title':'21天入門到放棄', 'src':'xxx.png' }, luffy_shopping_car_6_14:{ 'title':'21天入門到放棄', 'src':'xxx.png' } } """ # conn.flushall() # 添加課程 # redis_key = "luffy_shopping_car_%s_%s" %(7,12,) # conn.hmset(redis_key,{'title':'21天入門到放棄','src':'xxx.png'}) # 刪除課程 # conn.delete('luffy_shopping_car_6_12') # print(conn.keys()) # 修改課程 # conn.hset('luffy_shopping_car_6_11','src','x1.png') # print(conn.hget('luffy_shopping_car_6_11','src')) # 查看所有課程 # print(conn.keys("luffy_shopping_car_6_*")) # for item in conn.scan_iter('luffy_shopping_car_6_*',count=10): # course = conn.hgetall(item) # print(course) # conn.set('k1',123) # print(conn.type('luffy_shopping_car_6_11')) # print(conn.type('k1')) from django.core.cache import cache # print(conn.keys()) # # for key in conn.scan_iter("luffy_shopping_car_1*"): # # title = conn.hget(key,'title') # img = conn.hget(key, 'img') # policy = conn.hget(key, 'policy') # default_policy = conn.hget(key, 'default_policy') # # # print(str(title,encoding='utf-8')) # print(str(img,encoding='utf-8')) # print(json.loads(str(policy,encoding='utf-8'))) # print(str(default_policy,encoding='utf-8')) print(conn.keys()) conn.scan_iter() print(conn.exists('luffy_sg_car_1_1'))
九、redis 補充 - 分布式、高可用、讀寫分離
redis http://www.cnblogs.com/wupeiqi/articles/9348938.html 1. redis是什么? 是一個由C語言編寫的對內存進行存取數據的軟件(NoSQL數據庫;非關系型數據庫); 2. redis是單進程單線程的。 3. redis基礎: - 5大數據類型; - 字符串 - 列表 - 字典 - 集合 - 有序結合 - 發布和訂閱 - 事務 4. 主從 = 高可用 = HA 服務器A:10.211.55.19 redis-server /etc/redis-6379.conf # 內部bind:0.0.0.0 port: 6379 服務器B: 10.211.55.20 redis-server /etc/redis-6379.conf # 內部bind:0.0.0.0 port: 6379 slaveof: 10.211.55.19 特殊情況來了:如果主宕機,應該講從切換成主; 手動: - 登錄redis將從變成主 - 修改代碼,將連接字符串IP改成10.211.55.20 自動: - keepalived,監聽服務器的狀態做高可用;第三方組件; - sentinel(哨兵),檢測redis主服務器的狀態並將所有的slave獲取到,一旦主掛掉,則立即將從切換成主; redis-sentinel /etc/redis-sentinel-26379.conf(主IP,失敗個數) redis-sentinel /etc/redis-sentinel-26380.conf redis-sentinel /etc/redis-sentinel-26381.conf Python操作: from redis.sentinel import Sentinel # 連接哨兵服務器(主機名也可以用域名) sentinel = Sentinel([('10.211.55.20', 26379)],socket_timeout=0.5) # # 獲取主服務器地址 # master = sentinel.discover_master('mymaster') # print(master) # # # # 獲取從服務器地址 # slave = sentinel.discover_slaves('mymaster') # print(slave) # # # # # 獲取主服務器進行寫入 # master = sentinel.master_for('mymaster') # master.set('foo', 'bar') # # # # 獲取從服務器進行讀取(默認是round-roubin) # slave = sentinel.slave_for('mymaster', password='redis_auth_pass') # r_ret = slave.get('foo') # print(r_ret) 總結: - 高可用 - 讀寫分離 5. 集群=分布式 如何實現分布式集群: - codis,國產 豌豆莢 開源; - twemproxy,twitter開源 - cluster,redis官方提供 redis的cluster的原理? 16384槽位 服務器A: 0-5000 服務器B: 5001-10000 服務器B: 10001 - 16384 Python操作redis cluester: redis-py-cluster模塊 6. 分布式鎖 redlock算法 dlm = Redlock([{"host": "localhost", "port": 6379, "db": 0}, ]) # 如果 my_lock有值,則表示獲取鎖了 # 如果 my_lock無值,則表示未獲取鎖,別人獲取走了。 my_lock = dlm.lock("my_resource_name",1000) dlm.unlock(my_lock) # 刪除時調用lru腳本 redis分布式鎖實現原理: 1. 配置所有要連接的服務器並計算服務器一半的個數; 2. 獲取鎖: - 傳入參數:key,內部生成隨機字符串,超時時間 - 循環所有服務器,在服務器上設置: SET key 隨機字符串 NX PX 超時時間 # 如果已經存在則不設置 - 設置成功的個數 >= 一半+1 且 花費時間小於超時時間 3. 釋放鎖 - 刪除key和value(內部調用lru腳本) - 超時釋放 7. 其他: - 持久化: - AOF,記錄所有命令; - RDB,指定時間間隔做快照; - 過期策略 voltile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰 volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰 volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰 allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰 allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰 no-enviction(驅逐):禁止驅逐數據 - 不要是直接使用: - key - all 一定要使用scan_iter
十、redis 補充 - 應用
http://www.cnblogs.com/wupeiqi/articles/5132791.html
redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。


5、發布訂閱
發布者:服務器
訂閱者:Dashboad和數據處理
Demo如下:

訂閱者:
1
2
3
4
5
6
7
8
9
10
11
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
monitor.RedisHelper
import
RedisHelper
obj
=
RedisHelper()
redis_sub
=
obj.subscribe()
while
True
:
msg
=
redis_sub.parse_response()
print
msg
|
發布者:
1
2
3
4
5
6
7
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
monitor.RedisHelper
import
RedisHelper
obj
=
RedisHelper()
obj.public(
'hello'
)
|
6. sentinel
redis重的sentinel主要用於在redis主從復制中,如果master顧上,則自動將slave替換成master
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
redis.sentinel
import
Sentinel
# 連接哨兵服務器(主機名也可以用域名)
sentinel
=
Sentinel([(
'10.211.55.20'
,
26379
),
(
'10.211.55.20'
,
26380
),
],
socket_timeout
=
0.5
)
# # 獲取主服務器地址
# master = sentinel.discover_master('mymaster')
# print(master)
#
# # # 獲取從服務器地址
# slave = sentinel.discover_slaves('mymaster')
# print(slave)
#
#
# # # 獲取主服務器進行寫入
# master = sentinel.master_for('mymaster')
# master.set('foo', 'bar')
# # # # 獲取從服務器進行讀取(默認是round-roubin)
# slave = sentinel.slave_for('mymaster', password='redis_auth_pass')
# r_ret = slave.get('foo')
# print(r_ret)
|
更多參見:https://github.com/andymccurdy/redis-py/
http://doc.redisfans.com/