最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

Python教程学习之数据库Redis

XAMPP案例 admin 342浏览 0评论

drr00067

一、特点

二、与memcache比较

三、常见优化

四、redis过期策略【总共6种】

五、使用场景

六、Redis部署应用

1. 安装

2. 配置文件redis.conf

3. 持久化

3.1 RDB持久化配置

3.2 AOF持久化

4. redis主从复制实践

4.1 redis主从复制高可用哨兵模式【单台提供服务数据量级小】

5.  redis集群七、python操作redis

一、特点

  1. 速度快,存放与内存
  2. 支持丰富的数据类型:字符串、数组、集合、有序集合、hash
  3. 支持事务,操作都是原子性
  4. 支持持久化
  5. 16个库,默认0库【select  1】默认端口6379

二、与memcache比较

  1. memcache只支持字符串,redis支持5中
  2. redis要快
  3. redis支持持久化,memcache不支持
  4. redis支持value的max大小为1GB,memcache只1MB

三、常见优化

  1. 高可用,主从复制,使用单向链表结构,即:master < slave1 < slave2……这样的结构方便解决单点故障问题,实现slave对master的替换,如果master挂了,可以立即启用slave1做master,其它不变。
  2. master不做持久化工作,如果数据比较重要,某个slave开启aof备份,每秒同步一次
  3. master和slave在同一个局域网内,保持稳定性
  4. 避免在压力大的主库上增加从库

四、redis过期策略【总共6种】

结:从设置过期的数据集中,挑选使用少的,将要过期的,任意选,或者从总的数据中挑选使用少的,或任意,或不允许淘汰

  1. voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  2. volatile-tt1:从已设置过期时间的数据集,中挑选将要过期的数据淘汰
  3. volatile-random:从已设置过期时间的数据集,任意选择数据淘汰
  4. allkeys-lru: 从数据集中挑选最近最少使用的数据淘汰
  5. allkeys-random:从数据集中任意选择数据淘汰
  6. no-enviction(驱逐):禁止驱逐数据

五、使用场景

  1. 会话缓存,如购物车,权限信息
  2. 全页缓存
  3. 消息队列
  4. 排行榜、计数器
  5. 发布订阅,IM通讯

六、Redis部署应用

1. 安装

# 方式一:配置阿里yum源或epel源
yum list redis
yum install redis -y
systemctl start redis
# 查看连接
redis-cli
127.0.0.1:6379> ping

#方式二:编译安装,默认安装目录在/usr/local/bin
wget http://download.redis.io/releases/redis-4.0.10.tar.gztar -zxf redis-4.0.10.tar.gz
cd redis-4.0.10.tar.gz
make && make install
echo 'export PATH="$PATH:/usr/local/bin"' >> /etc/profile
source /etc/profile
# 启动
redis-server   # redis 可以开多实例,可以指定配置文件如:redis-server /redis_etc/redis_6379.conf
# 查看redis信息
redis-cli info   # 查看redis数据库信息
redis-cli info   replication  # 查看redis复制授权信息
redis-cli info   sentinel    # 查看哨兵信息

2. 配置文件redis.conf

#https://www.runoob.com/redis/redis-conf.html

# 网络-绑定主机地址【一个机器可能有多个ip,默认暴露所有】
bind 127.0.0.1  

# 网络-实例端口
port 6379

# 网络-保护模式,是否允许远程用户登录,哨兵时需要关闭【默认开启保护模式】
protected-mode yes

# 网络-配置密码【默认无密码】
requirepass redhat

# 完成tcp三次握手队列数,【默认511】
tcp-backlog 511

# 闲置300秒关闭连接 【默认0,不禁用】
timeout 300

# 开启长连接默认关闭即0
tcp-keepalive 0

# 开启守护模式,后台
daemonize yes

# 守护进程运行的pid位置
pidfile /var/run/redis.pid

# 日志记录级别
loglevel notice

# 记录日志的路劲
logfile "/app/redis_datas/rediscluster/logs/redis-7001.log"

# 选取得数据库,默认为1,有16个,select num 切换
databases 1

# 持久化同步数据文件 多少秒、更改多少个就进行同步
save 900 1
save 300 10
save 60 10000

# 当同步快照操作出错时停止写数据到磁盘,如果yes,后面写都失败
# 默认为yes,会照成rdb持久化并发写rdis,持续写,就会出现调用接口失败
# 当出现错误时,就可以临时将yes改为no
stop-writes-on-bgsave-error yes

# 对rdb数据进行压缩
rdbcompression yes

# 对rdb数据进行校验
rdbchecksum yes

# rdb文件名称
dbfilename 7001_dump.rdb

# redis文件存储路劲dir /app/redis_datas/rediscluster/7001

# 当前为从机时,与master失去连接时,是否继续提供服务,yes仅提供只读,但不保证数据是最新
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100

# 指定最大内存大小,申请那么大,启动时将数据放入
maxmemory 3072mb

# 过期淘汰6种中的,优先淘汰设置了过期,但最近没有使用的key
maxmemory-policy allkeys-lru

# aof日志开启,是否每次更新进行日志记录,默认no
appendonly no

# 指定更新日志文件名,默认
appendfilename "appendonly.aof"

# 每秒同步一次
appendfsync everysec

# 下面默认
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000

# 开启集群
cluster-enabled yes

# 集群的配置,配置文件首次启动自动生成 7000,7001,7002  
cluster-config-file /app/redis/redis-cluster-tmp-servers/7001/node7001.conf

# 请求超时默认15s
cluster-node-timeout 15000
#
cluster-migration-barrier 1

# 所有的槽ok,才提供服务、有16384个,生产一般为no
cluster-require-full-coverage yes
#
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

3. 持久化

redis 支持两种持久化RDB和AOF

  • RDB是在指定的时间间隔内生成数据集的时间点快照

优点:快,一般就是通过rdb做的

缺点:可能导致数据丢失

主要有:

# redis.conf中配置

save 900   1      1个修改类的操作, 即每过900秒,有1个操作就进行持久化
save 300   10     10个操作
save 60 10000     10000个操作
  • AOF是记录所有的操作命令,在服务器启动时重新执行

优点:安全最大程度保证数据不丢失

缺点:日志记录很大

3.1 RDB持久化配置
daemonize yes
port 6379
bind 10.0.0.10 127.0.0.1   #redis绑定地址
loglevel   warming
logfile /data/6379/redis.log
dir /data/6379             #定义持久化文件存储位置
dbfilename dbmp.rdb       #rdb持久化文件
requirepass redhat           #redis登录密码
save 900 1                   #rdb机制 每900秒 有1个修改记录
# save 300 10                   #每300秒       10个修改记录
# save 60 10000               #每60秒内       10000修改记录
3.2 AOF持久化
daemonize yes
port 6379
bind 10.0.0.10 127.0.0.1   #redis绑定地址
loglevel   warming
logfile /data/6379/redis.log
dir /data/6379
dbfilename dbmp.rdb
requirepass redhat
save 900 1
save 300 10
save 60 10000
appendonly yes     # 开启aof
appendfsync everysec   # 每秒进行一次
4. redis主从复制实践

master【主】

port 6379
bind 10.0.0.10
daemonize yes
logfile "6379.log"
dbfilename "dump-6379.rdb"
dir "/var/redis/data/"
masterauth redis   # 主库的密码

slave【从】

port 6380
bind 10.0.0.11
daemonize yes
logfile "6380.log"
dbfilename "dump-6380.rdb"
dir "/var/redis/data/"
slaveof 10.0.0.10 6379     # 从属主节点
masterauth redis   # 主库的密码

4.1 redis主从复制高可用哨兵模式【单台提供服务数据量级小】

sentinel 哨兵模式,通过它时刻监视master,每秒ping一下master,如果超过规定时间及次数,就标记master挂了,如果多个哨兵都认为其挂了,就选一个slave当master

1. 准备:一主二从

2. 自定义编辑sentinel_26379.conf文件

port 26379  
dir /var/redis/data/
logfile "26379.log"
# mymaster是主节点的别名
#当前Sentinel节点监控 10.0.0.10:6379 这个主节点
#2代表判断主节点失败至少需要2个Sentinel节点节点同意
sentinel monitor mymaster 10.0.0.10  6379 2
sentinel auth-pass mymaster redis
# 每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒30s且没有回复,则判定不可达
sentinel down-after-milliseconds mymaster 30000
# 当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,
#原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
sentinel parallel-syncs mymaster 1
# 故障转移超时时间为180000毫秒
sentinel failover-timeout mymaster 180000
protected-mode no   # 关闭保护模式,防止哨兵不能通信

3. 配置另2个sentinel文件,仅仅是端口不同而已

4. 启动哨兵

redis-sentinel /etc/redis-sentinel-26379.conf
redis-sentinel /etc/redis-sentinel-26380.conf
redis-sentinel /etc/redis-sentinel-26381.conf

5.  redis集群

哨兵模式解决单台能够满足的服务,数据量大时可以采用集群模式

# 1. 安装
wget http://download.redis.io/releases/redis-3.2.12.tar.gz && tar -zxf redis-3.2.12.tar.gz
make && make install PREFIX=/usr/local/redis-cluster

# 2. 集群配置:复制bin文件夹名为redis01,并将文件夹复制5份,合计6个文件夹,依次命名为redis01~redis06
cd /usr/local/redis-cluster && cd /bin && mv mv redis01 && for i in {2..6};do cp -r redis01 redis0$i;done;

# 3. 进入redis01,配置redis.conf文件
port 7001
daemonize yes
pidfile /var/run/redis.pid
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000

# 将配置好的redis.conf文件分别其他5个文件夹中,然后分别修改端口7002~6006
echo ../redis02 ../redis03 ../redis04 ../redis05 ../redis06 |xargs -n 1 cp -v redis.conf

# 4. 启动所有的节点
cd redis01 && ./redis-server redis.conf
cd ../redis02 && ./redis-server redis.conf
cd ../redis03 && ./redis-server redis.conf
cd ../redis04 && ./redis-server redis.conf
cd ../redis05 && ./redis-server redis.conf
cd ../redis06 && ./redis-server redis.conf
ps -ef |grep redis-server

# 5. 安装集群管理工具即复制安装包src下的redis-trib.rb【ruby脚本】
cp ~/redis-3.2.12/src/redis-trib.rb .
yum -y install ruby
yum install rubygems

# 6. 启动集群
## 使用create命令 --replicas 1 参数表示为每个主节点创建一个从节点,其他参数是实例的地址集合
[root@python-node01 redis-cluster]# ./redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
/usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- redis (LoadError)
from /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
from ./redis-trib.rb:25:in `<main>'

# 报错是因为rubygem问题,安装gem时报已安装,nothing to do,但实际需要和redis版本相同才行
# 添加国内源,删除国外源
gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/

wget https://rubygems.org/downloads/redis-3.3.2.gem

[root@python-node01 redis-cluster]# ./redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7001
127.0.0.1:7002
127.0.0.1:7003
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
Adding replica 127.0.0.1:7006 to 127.0.0.1:7003
M: 5de6caa94e4b0f135e9b9cc5af07ae2107eabc73 127.0.0.1:7001
  slots:0-5460 (5461 slots) master
M: 631ee5b8c5d8f0435c40ebc99cd7753e0c53f9a4 127.0.0.1:7002
  slots:5461-10922 (5462 slots) master
M: cdfb7aefc25226f94a8f9fe5b404d79fc6743ef2 127.0.0.1:7003
  slots:10923-16383 (5461 slots) master
S: ec0a0733fc394168e633ccbfcbaa28e5d321dd5e 127.0.0.1:7004
  replicates 5de6caa94e4b0f135e9b9cc5af07ae2107eabc73
S: 07fa14bdbe3d509f62da1ff545960ee1dda2f6ce 127.0.0.1:7005
  replicates 631ee5b8c5d8f0435c40ebc99cd7753e0c53f9a4
S: 7949f9c1c1e55b1acbcfba0805ae0e3b78dda926 127.0.0.1:7006
  replicates cdfb7aefc25226f94a8f9fe5b404d79fc6743ef2
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join...
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: 5de6caa94e4b0f135e9b9cc5af07ae2107eabc73 127.0.0.1:7001
  slots:0-5460 (5461 slots) master
  1 additional replica(s)
M: 631ee5b8c5d8f0435c40ebc99cd7753e0c53f9a4 127.0.0.1:7002
  slots:5461-10922 (5462 slots) master
  1 additional replica(s)
S: 7949f9c1c1e55b1acbcfba0805ae0e3b78dda926 127.0.0.1:7006
  slots: (0 slots) slave
  replicates cdfb7aefc25226f94a8f9fe5b404d79fc6743ef2
S: 07fa14bdbe3d509f62da1ff545960ee1dda2f6ce 127.0.0.1:7005
  slots: (0 slots) slave
  replicates 631ee5b8c5d8f0435c40ebc99cd7753e0c53f9a4
M: cdfb7aefc25226f94a8f9fe5b404d79fc6743ef2 127.0.0.1:7003
  slots:10923-16383 (5461 slots) master
  1 additional replica(s)
S: ec0a0733fc394168e633ccbfcbaa28e5d321dd5e 127.0.0.1:7004
  slots: (0 slots) slave
  replicates 5de6caa94e4b0f135e9b9cc5af07ae2107eabc73
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

# 7.新增集群节点
一样复制redis01文件夹的所有内容,并删除appendonly.aof、dump.rdb、nodes.conf文件
然后配置redis.conf,如端口变为7007,最后启动,最后执行如下命令,完成添加
前面表数要加的节点,后面表示要加的集群中的任意节点,标识加入到那个集群
[root@python-node01 redis-cluster]# ./redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001

# 8.新增节点未分配卡槽,故需手动迁移数据【7001节点是为了标识那个集群】
./redis-trib.rb reshard 127.0.0.1:7001
[OK] All 16384 slots covered.  
How many slots do you want to move (from 1 to 16384)?
提示我们需要迁移多少slot到7007上,我们平分16384个哈希槽给4个节点:16384/4 = 4096,我们需要移动4096个槽点到7007上

What is the receiving node ID?  
此处输入新增的节点id

Please enter all the source node IDs.  
Type 'all' to use all the nodes as source nodes for the hash slots.  
Type 'done' once you entered all the source nodes IDs.  
Source node #1: all # 表示从所有的节点中都拿一点卡槽的拼够4096个,也可以指定节点获取

# 8. 查看集群情况
[root@python-node01 redis07]# ./redis-cli -c -p 7007
127.0.0.1:7007> cluster nodes

七、python操作redis

1. 连接redis

import  redis
r_cli = redis.Redis(host='127.0.0.1', port=6379, password=123456)
r_cli.set('name', 'string_value')
ret = r_cli.get('name')  # 返回的都是bytes

2. 连接池

pool = redis.ConnectionPool(host='localhost', port=6379, password=123456)
r_cli = redis.Redis(connection_pool=pool,max_connections=100)

3. 五种数据类型操作

# str字符串
r_cli.set('name', 'sun')
r_cli.get('name')

r_cli.mset({'name1': 11, 'name': 22})
r_cli.mget('name1', 'name')
ret = r_cli.mget(['name1', 'name'])

# hash字典
r_cli.hset('hash_name', 'project', 'age')
r_cli.hget('hash_name', 'project')

r_cli.hmset('namexxx', {'1': 1, '2': 2, '3': 3})
r_cli.hmget('namexxx', '1', '2')
r_cli.hmget('namexxx', ['1', '2'])
r_cli.hgetall('namexxx')

# list列表
r_cli.lpush('li_name', 1, 2, 3)
r_cli.lrange('li_name', 0, -1)  # 按索引范围获取
r_cli.llen('li_name')
r_cli.lpop('li_name')  # 删左边第一个,返回删除值

# 集合
r_cli.sadd('set_name', 1, 2, 3)
r_cli.smembers('set_name')  # 获取集合所有值
r_cli.spop('set_name')  # 从后面删

# 有序集合
r_cli.zadd('zadd_name', {'wuhan': 1000, 'bj': 100})  # 前面是key,后面是分值
r_cli.zcard('zadd_name')  # 获取name的集合元素数量
r_cli.zcount('zadd_name', 0, 100)  # 获取分值在0~100间的个数
r_cli.zrange('zadd_name', 0, -1)  # 按索引获取对应name的key

4. 实用工具类

import redis
import threading
from rediscluster import StrictRedisCluster


# 单连
class RedisPoolUtil(object):
   """
  多个redis实例共享同一个连接池
  """
   _instance_lock = threading.Lock()

   def __init__(self):
       if not hasattr(RedisPoolUtil, 'pool'):
           RedisPoolUtil.create_pool()
       self.conn = redis.Redis(connection_pool=RedisPoolUtil.pool)

   def __new__(cls, *args, **kwargs):
       if not hasattr(RedisPoolUtil, '_instance'):
           with RedisPoolUtil._instance_lock:
               if not hasattr(RedisPoolUtil, '_instance'):
                   RedisPoolUtil._instance = object.__new__(cls)
       return RedisPoolUtil._instance

   @classmethod
   def create_pool(cls):
       RedisPoolUtil.pool = redis.ConnectionPool(
           host="localhost",
           port=6379,
           password=None,
           db=0,
           max_connections=100)


# 集群
class RedisCluster(object):
   """
  redis集群连接
  """

   def __init__(self, conn_list=None, password=None):
       """
      :param conn_list: 集群节点host
      :param password: 集群连接密码
      """
       self.conn_list = conn_list
       self.password = password

   def connect(self):
       """
      连接redis集群
      :return: conn,err
      """

       try:
           # 非密码连接redis集群
           # redis_conn = StrictRedisCluster(startup_nodes=self.conn_list)
           # 使用密码连接redis集群
           redis_conn = StrictRedisCluster(startup_nodes=self.conn_list,
                                           password=self.password, decode_responses=True)
           return redis_conn, None
       except Exception as e:
           err = "连接redis集群失败,错误信息:%s" % e.message
           return False, err

转载请注明:XAMPP中文组官网 » Python教程学习之数据库Redis

您必须 登录 才能发表评论!