redis进阶
redis发布订阅
参考文章:https://pythonav.com/wiki/detail/3/33/
1.subscribe
- 订阅一个或者多个频道
2.publish
- 给指定的频道发消息
3.psubscribe
- 订阅指定模式的消息频道,*代表所有
4.pubsub channels
- 查看当前活跃频道
5.Pubsub numsub channels
- 查看当前频道的订阅人数
6.pubsub numpat
- 返回订阅模式的数量
发送端
Windows PowerShell
版权所有 (C) 2009 Microsoft Corporation。保留所有权利。
PS C:\Users\Administrator> redis-cli
127.0.0.1:6379> auth foobared
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> publish s22 helloworld
(integer) 1
127.0.0.1:6379> publish s22 helloworld2
(integer) 0
127.0.0.1:6379> publish s22 helloworld2
(integer) 0
127.0.0.1:6379> publish s22.hello hekk
(integer) 1
127.0.0.1:6379> pubsub channels
(empty list or set)
127.0.0.1:6379> publish s22.hello hekk
(integer) 1
127.0.0.1:6379> publish s22.hello hekk
(integer) 1
127.0.0.1:6379> pubsub channels
(empty list or set)
127.0.0.1:6379> pubsub numsub s22
1) "s22"
2) (integer) 0
127.0.0.1:6379> pubsub channels
1) "s22"
127.0.0.1:6379> pubsub numsub s22
1) "s22"
2) (integer) 1
127.0.0.1:6379> pubsub namapt
(error) ERR Unknown PUBSUB subcommand or wrong number of arguments for 'namapt'
127.0.0.1:6379> pubsub numpat
(integer) 1
127.0.0.1:6379>
订阅
(djangozp) E:\project\prozhjy\djangozp>redis-cli
127.0.0.1:6379> auth foobared
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> subscribe s22
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "s22"
3) (integer) 1
1) "message"
2) "s22"
3) "helloworld"
^C
(djangozp) E:\project\prozhjy\djangozp>
(djangozp) E:\project\prozhjy\djangozp>redis-cli
127.0.0.1:6379> auth foobared
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> psubscribe s22.*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "s22.*"
3) (integer) 1
1) "pmessage"
2) "s22.*"
3) "s22.hello"
4) "hekk"
1) "pmessage"
2) "s22.*"
3) "s22.hello"
4) "hekk"
1) "pmessage"
2) "s22.*"
3) "s22.hello"
4) "hekk"
另一个订阅
redis的配置文件
redis启动默认占用终端
修改redis.conf中的dameonize no
,将no修改为yes则redis启动将不在占用终端,即设置是否守护进程的模式运行;
-
密码设置
-
require pass foonared
-
登录命令
AUTH FOOBARED
redis主从配置
只需要在从服务器上进行配置
slaveof ip地址 端口
如果有密码的话,在设置
master auth <password>
密码也可以使用命令行配置
config set masterauth password
- 基于异步的,平均每秒钟从服务器都会往主服务
发送赋值情况
- 一个主可以有多个从
- 不止主可以有从服务器,从也可以有从服务器
- 复制功能不会阻塞主服务器
- 复制功能也不会阻塞从服务器
redis持久化存储
-
两种方式
- rdb
- aof
1.rdb
-
配置文件
-
优点
- 生成二进制文件
- 系统会默认多长时间保存一次
- 直接保存
- 制作快照
- 可以用作备份
- 比较适合作灾难恢复
- 主进程会fork一个子进程出来,子进程用来复制保存数据
-
缺点
- 如果说数据需要尽量保存下来,则不适用rdb
- 在数据量庞大的时候,对系统(cpu)消耗过大
-
配置方法
SAVE 900 1#900秒内有一次变化就会持久化 save 300 10 save 60 10000 默认存在 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb #数据保存文件 dir ./ 保存目录
2.AOF
-
优点
- 持久化更好
- aof将所有的操作追加到一个文件中,redis-check-aof
- 文件易读
-
缺点
- 文件会越来越大
- aof的速度会比rdb慢,aof 使用的是fsync
- 文件易读,安全性较低
-
配置方式
配置文件中 需修改 appendonly yes 默认存在 appendfilename "appendonly.aof" appendfsync everysec
3.rdb切换到aof
config set appendonly yes
config set save ""
不重启redis切换
-
补充
-
flushall:清空所有数据
4.redis高可用
redis中实现高可用的技术主要有持久化、复制、哨兵、集群
-
持次化:持久化是最简单的可方法。它的主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
-
复制:复制是高可用Redis的基础,哨兵和集群都是在复制基础.上实现高可用的。复制主要实现了数据的多机备份以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化、写操作无负载均衡、存储能力受到单机的限制。
-
哨兵:在复制的基础上,哨兵实现了自动化的故障恢复。缺陷是写操作无法负载均衡,存储能力受到单机的限制。
-
集群:通过集群,Redis解决了写操作无法负载均衡以及存储能力受到单机限制的问题,实现了
较为善的訶肪案。
4.1redis哨兵
参考文章https://pythonav.com/wiki/detail/3/33/#8.4%20redis%E5%93%A8%E5%85%B5
redis3之前哨兵使用广泛,现在使用集群较多;
4.2 redis集群
-
客户端分片
-
redis实例集群主要思想是将redis数据的key进行散列,通过hash函数特定的key会映射到指定的redis节点上
-
数据分布原理图
-
分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。
常见的分区规则有哈希分区和顺序分区。
Redis Cluster
采用哈希分区规则,因此接下来会讨论哈希分区规则。- 节点取余分区
- 一致性哈希分区
- 虚拟槽分区(redis-cluster采用的方式)
-
例如按照节点取余的方式,分三个节点
1~100的数据对3取余,可以分为三类
- 余数为0
- 余数为1
- 余数为2
那么同样的分4个节点就是hash(key)%4
节点取余的优点是简单,客户端分片直接是哈希+取余
虚拟槽分区
-
Redis Cluster
采用虚拟槽分区虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合,整数定义为槽(slot)。
Redis Cluster槽的范围是0 ~ 16383。
槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展,
每个节点负责一定数量的槽。
-
-
搭建redis-cluster
-
搭建集群分为几部
- 准备节点(几匹马儿)
- 节点通信(几匹马儿分配主从)
- 分配槽位给节点(slot分配给马儿)
-
多个服务端,负责读写,彼此通信,redis指定了16384个槽。 多匹马儿,负责运输数据,马儿分配16384个槽位,管理数据。 ruby的脚本自动就把分配槽位这事做了
-
步骤一、通过配置,redis.conf开启redis-cluster
port 7000daemonize yesdir "/opt/redis/data"logfile "7000.log"dbfilename "dump-7000.rdb"cluster-enabled yes #开启集群模式cluster-config-file nodes-7000.conf #集群内部的配置文件cluster-require-full-coverage no #redis cluster需要16384个slot都正常的时候才能对外提供服务,换句话说,只要任何一个slot异常那么整个cluster不对外提供服务。 因此生产环境一般为no
redis支持多实例的功能,我们在单机演示集群搭建,需要6个实例,三个是主节点,三个是从节点,数量为6个节点才能保证高可用的集群。
每个节点仅仅是端口运行的不同!
[root@yugo /opt/redis/config 17:12:30]#lsredis-7000.conf redis-7002.conf redis-7004.confredis-7001.conf redis-7003.conf redis-7005.conf#确保每个配置文件中的端口修改!!
步骤二、运行redis实例
创建6个节点的redis实例
1855 2018-10-24 15:46:01 redis-server redis-7000.conf 1856 2018-10-24 15:46:13 redis-server redis-7001.conf 1857 2018-10-24 15:46:16 redis-server redis-7002.conf 1858 2018-10-24 15:46:18 redis-server redis-7003.conf 1859 2018-10-24 15:46:20 redis-server redis-7004.conf 1860 2018-10-24 15:46:23 redis-server redis-7005.conf redis-server redis-7000.confredis-server redis-7001.confredis-server redis-7002.confredis-server redis-7003.confredis-server redis-7004.confredis-server redis-7005.conf
步骤3、开启redis-cluster
- 下载、编译、安装Ruby语言
- 安装rubygem redis
- 安装redis-trib.rb命令
第一步、安装ruby
#下载ruby源码包wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz#解压缩ruby源码包tar -zxvf ruby-2.3.1.tar.gz#编译且安装./configure --prefix=/opt/ruby/make && make install
第二步、配置ruby环境变量
vim /etc/profile写入如下配置PATH=$PATH:/opt/ruby/bin
第三步、安装ruby操作redis包
wget http://rubygems.org/downloads/redis-3.3.0.gemgem install -l redis-3.3.0.gem
第四部、安装redis-trib.rb命令
[root@yugo /opt/redis/src 18:38:13]#cp /opt/redis/src/redis-trib.rb /usr/local/bin/
一键开启redis-cluster集群
#每个主节点,有一个从节点,代表--replicas 1redis-trib.rb create --replicas 1 127.0.0.1:7000 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#集群自动分配主从关系 7000、7001、7002为 7003、7004、7005 主动关系
查看集群状态
redis-cli -p 7000 cluster info redis-cli -p 7000 cluster nodes #等同于查看nodes-7000.conf文件节点信息集群主节点状态redis-cli -p 7000 cluster nodes | grep master集群从节点状态redis-cli -p 7000 cluster nodes | grep slave
写入redis-cluster集群数据
安装完毕后,检查集群状态
[root@yugo /opt/redis/src 18:42:14]#redis-cli -p 7000 cluster infocluster_state:okcluster_slots_assigned:16384cluster_slots_ok:16384cluster_slots_pfail:0cluster_slots_fail:0cluster_known_nodes:6cluster_size:3cluster_current_epoch:6cluster_my_epoch:1cluster_stats_messages_ping_sent:10468cluster_stats_messages_pong_sent:10558cluster_stats_messages_sent:21026cluster_stats_messages_ping_received:10553cluster_stats_messages_pong_received:10468cluster_stats_messages_meet_received:5cluster_stats_messages_received:21026
测试写入集群数据,登录集群必须使用redis-cli -c -p 7000必须加上-c参数
127.0.0.1:7000> set name chao -> Redirected to slot [5798] located at 127.0.0.1:7001 OK127.0.0.1:7001> exit[root@yugo /opt/redis/src 18:46:07]#redis-cli -c -p 7000127.0.0.1:7000> pingPONG127.0.0.1:7000> keys *(empty list or set)127.0.0.1:7000> get name-> Redirected to slot [5798] located at 127.0.0.1:7001"chao"
6. redis-python api
1、对redis的单实例进行连接操作python3>>>import redis>>>r = redis.StrictRedis(host='localhost', port=6379, db=0,password='root')>>>r.set('lufei', 'guojialei')True>>>r.get('lufei')'bar'--------------------2、sentinel集群连接并操作[root@db01 ~]# redis-server /data/6380/redis.conf[root@db01 ~]# redis-server /data/6381/redis.conf[root@db01 ~]# redis-server /data/6382/redis.conf [root@db01 ~]# redis-sentinel /data/26380/sentinel.conf &--------------------------------## 导入redis sentinel包>>> from redis.sentinel import Sentinel ##指定sentinel的地址和端口号>>> sentinel = Sentinel([('localhost', 26380)], socket_timeout=0.1) ##测试,获取以下主库和从库的信息>>> sentinel.discover_master('mymaster') >>> sentinel.discover_slaves('mymaster') ##配置读写分离#写节点>>> master = sentinel.master_for('mymaster', socket_timeout=0.1) #读节点>>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1) ###读写分离测试 key >>> master.set('oldboy', '123') >>> slave.get('oldboy') '123'----------------------redis cluster的连接并操作(python2.7.2以上版本才支持redis cluster,我们选择的是3.5)https://github.com/Grokzen/redis-py-cluster3、python连接rediscluster集群测试使用python3>>> from rediscluster import StrictRedisCluster >>> startup_nodes = [{"host": "127.0.0.1", "port": "7000"}] ### Note: decode_responses must be set to True when used with python3 >>> rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True) >>> rc.set("foo", "bar") True >>> 'bar'