八、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(主从)同步。

View Code
实现计数器

5、发布订阅

django - 总结 - redis缓存

发布者:服务器

订阅者:Dashboad和数据处理

Demo如下:

RedisHelper

订阅者:

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/

八、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(主从)同步。

View Code
实现计数器

5、发布订阅

django - 总结 - redis缓存

发布者:服务器

订阅者:Dashboad和数据处理

Demo如下:

RedisHelper

订阅者:

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/