Redis进阶概述
redis发布订阅
发布publish
订阅subscribe
Redis 通过 PUBLISH 、 SUBSCRIBE 等命令实现了订阅与发布模式。
举例1:
qq群的公告,单个发布者,多个收听者
发布/订阅 实验
发布订阅的命令
PUBLISH channel msg 将信息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel ...] 订阅频道,可以同时订阅多个频道
UNSUBSCRIBE [channel ...] 取消订阅指定的频道, 如果不指定频道,则会取消订阅所有频道 PSUBSCRIBE pattern [pattern ...] 订阅一个或多个符合给定模式的频道,每个模式以 * 作为匹配符,比如 it* 匹配所 有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有 以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类 PUNSUBSCRIBE [pattern [pattern ...]] 退订指定的规则, 如果没有参数则会退订所有规则 PUBSUB subcommand [argument [argument ...]] 查看订阅与发布系统状态 注意:使用发布订阅模式实现的消息队列,当有客户端订阅channel后只能收到后续发布到该频道的消息,之前发送的不会缓存,必须Provider和Consumer同时在线。
发布订阅:
窗口1,启动两个redis-cli窗口,均订阅diantai 频道(channel)
窗口2,启动发布者向频道 diantai发送消息
[root@web02 ~]# redis-cli 127.0.0.1:6379> PUBLISH diantai 'jinyewugenglaiwojia' (integer) 2
窗口3,查看订阅者的消息状态
订阅一个或者多个符合模式的频道
窗口1,启动两个redis-cli窗口,均订阅 wang*频道(channel)
127.0.0.1:6379> PSUBSCRIBE wang* Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "wang*" 3) (integer) 1
1) "pmessage" 2) "wang*" 3) "wangbaoqiang" 4) "jintian zhennanshou "
窗口2,启动redis-cli窗口,均订阅wang*频道
127.0.0.1:6379> PSUBSCRIBE wang* Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "wang*" 3) (integer) 1 1) "pmessage" 2) "wang*" 3) "wangbaoqiang" 4) "jintian zhennanshou "
窗口3,发布者消息
[root@web02 ~]# redis-cli 127.0.0.1:6379> PUBLISH wangbaoqiang "jintian zhennanshou " (integer) 2
redis持久化RDB与AOF
redis持久化
Redis
是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题,Redis
提供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的丢失。
RDB持久化
redis
提供了RDB持久化
的功能,这个功能可以将redis
在内存中的的状态保存到硬盘中,它可以手动执行。
也可以再redis.conf
中配置,定期执行。
RDB持久化产生的RDB文件是一个经过压缩的二进制文件,这个文件被保存在硬盘中,redis可以通过这个文件还原数据库当时的状态。
RDB(持久化) 内存数据保存到磁盘 在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot) 优点:速度快,适合做备份,主从复制就是基于RDB持久化功能实现 rdb通过再redis中使用save命令触发 rdb rdb配置参数: dir /data/6379/ dbfilename dbmp.rdb 每过900秒 有1个操作就进行持久化 save 900秒 1个修改类的操作 save 300秒 10个操作 save 60秒 10000个操作 save 900 1 save 300 10 save 60 10000
redis持久化之RDB实践
1.启动redis服务端,准备配置文件
daemonize yes port 6379 logfile /data/6379/redis.log dir /data/6379 #定义持久化文件存储位置 dbfilename dbmp.rdb #rdb持久化文件 bind 10.0.0.10 127.0.0.1 #redis绑定地址 requirepass redhat #redis登录密码 save 900 1 #rdb机制 每900秒 有1个修改记录 save 300 10 #每300秒 10个修改记录 save 60 10000 #每60秒内 10000修改记录
2.启动redis服务端
3.登录redis设置一个key
redis-cli -a redhat
4.此时检查目录,/data/6379底下没有dbmp.rdb文件
5.通过save触发持久化,将数据写入RDB文件
127.0.0.1:6379> set age 18 OK 127.0.0.1:6379> save OK
redis持久化之AOF
AOF(append-only log file)
记录服务器执行的所有变更操作命令(例如set del等),并在服务器启动时,通过重新执行这些命令来还原数据集
AOF 文件中的命令全部以redis协议的格式保存,新命令追加到文件末尾。
优点:最大程序保证数据不丢
缺点:日志记录非常大
redis-client 写入数据 > redis-server 同步命令 > AOF文件
配置参数
AOF持久化配置,两条参数
appendonly yes
appendfsync always 总是修改类的操作
everysec 每秒做一次持久化
no 依赖于系统自带的缓存大小机制
1.准备aof配置文件 redis.conf
daemonize yes port 6379 logfile /data/6379/redis.log dir /data/6379 dbfilename dbmp.rdb requirepass redhat save 900 1 save 300 10 save 60 10000 appendonly yes appendfsync everysec
2.启动redis服务
redis-server /etc/redis.conf
3.检查redis数据目录/data/6379/是否产生了aof文件
[root@web02 6379]# ls appendonly.aof dbmp.rdb redis.log
4.登录redis-cli,写入数据,实时检查aof文件信息
[root@web02 6379]# tail -f appendonly.aof
5.设置新key,检查aof信息,然后关闭redis,检查数据是否持久化
redis-cli -a redhat shutdown redis-server /etc/redis.conf redis-cli -a redhat
redis 持久化方式有哪些?有什么区别?
rdb:基于快照的持久化,速度更快,一般用作备份,主从复制也是依赖于rdb持久化功能
aof:以追加的方式记录redis操作日志的文件。可以最大程度的保证redis数据安全,类似于mysql的binlog
redis不重启,切换RDB备份到AOF备份
确保redis版本在2.2以上
[root@pyyuc /data 22:23:30]#redis-server -v Redis server v=4.0.10 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=64cb6afcf41664c
本文在redis4.0中,通过config set命令,达到不重启redis服务,从RDB持久化切换为AOF
实验环境准备
redis.conf服务端配置文件
daemonize yes port 6379 logfile /data/6379/redis.log dir /data/6379 dbfilename dbmp.rdb save 900 1 #rdb机制 每900秒 有1个修改记录 save 300 10 #每300秒 10个修改记录 save 60 10000 #每60秒内 10000修改记录
启动redis服务端
redis-server redis.conf
登录redis-cli插入数据,手动持久化
127.0.0.1:6379> set name chaoge OK 127.0.0.1:6379> set age 18 OK 127.0.0.1:6379> set addr shahe OK 127.0.0.1:6379> save OK
检查RDB文件
[root@pyyuc /data 22:34:16]#ls 6379/ dbmp.rdb redis.log
备份这个rdb文件,保证数据安全
[root@pyyuc /data/6379 22:35:38]#cp dbmp.rdb /opt/
执行命令,开启AOF持久化
127.0.0.1:6379> CONFIG set appendonly yes #开启AOF功能 OK 127.0.0.1:6379> CONFIG SET save "" #关闭RDB功能 OK
确保数据库的key数量正确
127.0.0.1:6379> keys * 1) "addr" 2) "age" 3) "name"
确保插入新的key,AOF文件会记录
127.0.0.1:6379> set title golang OK
此时RDB已经正确切换AOF,注意还得修改redis.conf添加AOF设置,不然重启后,通过config set的配置将丢失
redis主从同步
redis主从同步
原理:
1. 从服务器向主服务器发送 SYNC 命令。
2. 接到 SYNC 命令的主服务器会调用BGSAVE 命令,创建一个 RDB 文件,并使用缓冲区记录接下来执行的所有写命令。
3. 当主服务器执行完 BGSAVE 命令时,它会向从服务器发送 RDB 文件,而从服务器则会接收并载入这个文件。
4. 主服务器将缓冲区储存的所有写命令发送给从服务器执行。
-------------
1、在开启主从复制的时候,使用的是RDB方式的,同步主从数据的
2、同步开始之后,通过主库命令传播的方式,主动的复制方式实现
3、2.8以后实现PSYNC的机制,实现断线重连
环境准备
6380.conf
1、环境: 准备两个或两个以上redis实例 mkdir /data/638{0..2} #创建6380 6381 6382文件夹 配置文件示例: vim /data/6380/redis.conf port 6380 daemonize yes pidfile /data/6380/redis.pid loglevel notice logfile "/data/6380/redis.log" dbfilename dump.rdb dir /data/6380 protected-mode no
6381.conf
vim /data/6381/redis.conf port 6381 daemonize yes pidfile /data/6381/redis.pid loglevel notice logfile "/data/6381/redis.log" dbfilename dump.rdb dir /data/6381 protected-mode no
6382.conf
port 6382 daemonize yes pidfile /data/6382/redis.pid loglevel notice logfile "/data/6382/redis.log" dbfilename dump.rdb dir /data/6382 protected-mode no
启动三个redis实例
redis-server /data/6380/redis.conf redis-server /data/6381/redis.conf redis-server /data/6382/redis.conf
主从规划
主节点:6380 从节点:6381、6382
配置主从同步
6381/6382命令行
redis-cli -p 6381
SLAVEOF 127.0.0.1 6380 #指明主的地址
redis-cli -p 6382
SLAVEOF 127.0.0.1 6380 #指明主的地址
检查主从状态
从库:
127.0.0.1:6382> info replication 127.0.0.1:6381> info replication
主库:
127.0.0.1:6380> info replication
测试写入数据,主库写入数据,检查从库数据
主 127.0.0.1:6380> set name chaoge 从 127.0.0.1:6381>get name
手动进行主从复制故障切换
#关闭主库6380
redis-cli -p 6380 shutdown
检查从库主从信息,此时master_link_status:down
redis-cli -p 6381 info replication
redis-cli -p 6382
info replication
既然主库挂了,我想要在6381 6382之间选一个新的主库
1.关闭6381的从库身份
redis-cli -p 6381 info replication slaveof no one
2.将6382设为6381的从库
6382连接到6381: [root@db03 ~]# redis-cli -p 6382 127.0.0.1:6382> SLAVEOF no one 127.0.0.1:6382> SLAVEOF 127.0.0.1 6381
3.检查6382,6381的主从信息
redis-sentinel主从复制高可用
Redis-Sentinel
Redis-Sentinel是redis官方推荐的高可用性解决方案,
当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户端都没有实现主从切换的功能。
而redis-sentinel就是一个独立运行的进程,用于监控多个master-slave集群,
自动发现master宕机,进行自动切换slave > master。
sentinel主要功能如下:
- 不时的监控redis是否良好运行,如果节点不可达就会对节点进行下线标识
- 如果被标识的是主节点,sentinel就会和其他的sentinel节点“协商”,如果其他节点也人为主节点不可达,就会选举一个sentinel节点来完成自动故障转义
- 在master-slave进行切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
Sentinel的工作方式:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次 若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。 主观下线和客观下线 主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断。 客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover. SDOWN适合于Master和Slave,只要一个 Sentinel 发现Master进入了ODOWN, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对下线的主服务器执行自动故障迁移操作。 ODOWN只适用于Master,对于Slave的 Redis 实例,Sentinel 在将它们判断为下线前不需要进行协商, 所以Slave的 Sentinel 永远不会达到ODOWN。
redis主从复制背景问题
Redis
主从复制可将主节点数据同步给从节点,从节点此时有两个作用:
- 一旦主节点宕机,从节点作为主节点的备份可以随时顶上来。
- 扩展主节点的读能力,分担主节点读压力。
但是问题是:
- 一旦主节点宕机,从节点上位,那么需要人为修改所有应用方的主节点地址(改为新的master地址),还需要命令所有从节点复制新的主节点
那么这个问题,redis-sentinel就可以解决了
主从复制架构
Redis Sentinel架构
redis的一个进程,但是不存储数据,只是监控redis
redis命令整理
官网地址:http://redisdoc.com/ redis-cli info #查看redis数据库信息 redis-cli info replication #查看redis的复制授权信息
redis-cli info sentinel #查看redis的哨兵信息
安装与配置
本实验是在测试环境下,考虑到学生机器较弱,因此只准备一台linux服务器用作环境!!
服务器环境,一台即可完成操作
master 192.168.119.10
所有配置文件如下
主节点master的redis-6379.conf
port 6379 daemonize yes logfile "6379.log" dbfilename "dump-6379.rdb" dir "/var/redis/data/"
从节点slave的redis-6380.conf
port 6380 daemonize yes logfile "6380.log" dbfilename "dump-6380.rdb" dir "/var/redis/data/" slaveof 127.0.0.1 6379 // 从属主节点
从节点slave的redis-6381.conf
port 6381 daemonize yes logfile "6380.log" dbfilename "dump-6380.rdb" dir "/var/redis/data/" slaveof 127.0.0.1 6379 // 从属主节点
启动redis主节点
redis-server /etc/redis-6379.conf
测试redis主节点是否通信
redis-cli ping
启动两slave节点
还记得上面超哥的截图吗?总体redis配置文件如下,6379为master,6380和6381为slave
-rw-r--r-- 1 root root 145 Nov 7 17:44 /etc/redis-6379.conf #这个为主,port是6379 -rw-r--r-- 1 root root 93 Nov 7 17:42 /etc/redis-6380.conf # 这个是从,port6380,并且得加上新的参数slaveof -rw-r--r-- 1 root root 115 Nov 7 17:42 /etc/redis-6381.conf # 这个是从,port6381,并且得加上新的参数slaveof
redis-6380.conf slave配置文件详解,6381端口的配置文件,仅仅和6380端口不一样
port 6380 daemonize yes logfile "6379.log" dbfilename "dump-6379.rdb" dir "/var/redis/data" # Generated by CONFIG REWRITE slaveof 127.0.0.1 6379
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# Redis 配置文件 # 当配置中需要配置内存大小时,可以使用 1k, 5GB, 4M 等类似的格式,其转换方式如下(不区分大小写) # # 1k => 1000 bytes # 1kb => 1024 bytes # 1m => 1000000 bytes # 1mb => 1024*1024 bytes # 1g => 1000000000 bytes # 1gb => 1024*1024*1024 bytes # # 内存配置大小写是一样的.比如 1gb 1Gb 1GB 1gB # daemonize no 默认情况下,redis不是在后台运行的,如果需要在后台运行,把该项的值更改为yes daemonize yes # 当redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你可以配置到其他地址。 # 当运行多个redis服务时,需要指定不同的pid文件和端口 pidfile /var/run/redis.pid # 指定redis运行的端口,默认是6379 port 6379 # 指定redis只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求, # 在生产环境中最好设置该项 # bind 127.0.0.1 # Specify the path for the unix socket that will be used to listen for # incoming connections. There is no default, so Redis will not listen # on a unix socket when not specified. # # unixsocket /tmp/redis.sock # unixsocketperm 755 # 设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接 # 0是关闭此设置 timeout 0 # 指定日志记录级别 # Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose # debug 记录很多信息,用于开发和测试 # varbose 有用的信息,不像debug会记录那么多 # notice 普通的verbose,常用于生产环境 # warning 只有非常重要或者严重的信息会记录到日志 loglevel debug # 配置log文件地址 # 默认值为stdout,标准输出,若后台模式会输出到/dev/null #logfile stdout logfile /var/log/redis/redis.log # To enable logging to the system logger, just set 'syslog-enabled' to yes, # and optionally update the other syslog parameters to suit your needs. # syslog-enabled no # Specify the syslog identity. # syslog-ident redis # Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. # syslog-facility local0 # 可用数据库数 # 默认值为16,默认数据库为0,数据库范围在0-(database-1)之间 databases 16 ################################ 快照 ################################# # # 保存数据到磁盘,格式如下: # # save <seconds> <changes> # # 指出在多长时间内,有多少次更新操作,就将数据同步到数据文件rdb。 # 相当于条件触发抓取快照,这个可以多个条件配合 # # 比如默认配置文件中的设置,就设置了三个条件 # # save 900 1 900秒内至少有1个key被改变 # save 300 10 300秒内至少有300个key被改变 # save 60 10000 60秒内至少有10000个key被改变 save 900 1 save 300 10 save 60 10000 # 存储至本地数据库时(持久化到rdb文件)是否压缩数据,默认为yes rdbcompression yes # 本地持久化数据库文件名,默认值为dump.rdb dbfilename dump.rdb # 工作目录 # # 数据库镜像备份的文件放置的路径。 # 这里的路径跟文件名要分开配置是因为redis在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成时, # 再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。 # # AOF文件也会存放在这个目录下面 # # 注意这里必须制定一个目录而不是文件 dir ./ ################################# 复制 ################################# # 主从复制. 设置该数据库为其他数据库的从数据库. # 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步 # # slaveof <masterip> <masterport> # 当master服务设置了密码保护时(用requirepass制定的密码) # slav服务连接master的密码 # # masterauth <master-password> # 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式: # # 1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续相应客户端的请求 # # 2) 如果slave-serve-stale-data是指为no,出去INFO和SLAVOF命令之外的任何请求都会返回一个 # 错误"SYNC with master in progress" # slave-serve-stale-data yes # 从库会按照一个时间间隔向主库发送PINGs.可以通过repl-ping-slave-period设置这个时间间隔,默认是10秒 # # repl-ping-slave-period 10 # repl-timeout 设置主库批量数据传输时间或者ping回复时间间隔,默认值是60秒 # 一定要确保repl-timeout大于repl-ping-slave-period # repl-timeout 60 ################################## 安全 ################################### # 设置客户端连接后进行任何其他指定前需要使用的密码。 # 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解 # # requirepass foobared # 命令重命名. # # 在一个共享环境下可以重命名相对危险的命令。比如把CONFIG重名为一个不容易猜测的字符。 # # 举例: # # rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 # # 如果想删除一个命令,直接把它重命名为一个空字符""即可,如下: # # rename-command CONFIG "" ################################### 约束 #################################### # 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数, # 如果设置 maxclients 0,表示不作限制。 # 当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息 # # maxclients 128 # 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key # Redis同时也会移除空的list对象 # # 当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作 # # 注意:Redis新的vm机制,会把Key存放内存,Value会存放在swap区 # # maxmemory的设置比较适合于把redis当作于类似memcached的缓存来使用,而不适合当做一个真实的DB。 # 当把Redis当做一个真实的数据库使用的时候,内存使用将是一个很大的开销 # maxmemory <bytes> # 当内存达到最大值的时候Redis会选择删除哪些数据?有五种方式可供选择 # # volatile-lru -> 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used ) # allkeys-lru -> 利用LRU算法移除任何key # volatile-random -> 移除设置过过期时间的随机key # allkeys->random -> remove a random key, any key # volatile-ttl -> 移除即将过期的key(minor TTL) # noeviction -> 不移除任何可以,只是返回一个写错误 # # 注意:对于上面的策略,如果没有合适的key可以移除,当写的时候Redis会返回一个错误 # # 写命令包括: set setnx setex append # incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd # sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby # zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby # getset mset msetnx exec sort # # 默认是: # # maxmemory-policy volatile-lru # LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法(为了节省内存),随意你可以选择样本大小进行检测。 # Redis默认的灰选择3个样本进行检测,你可以通过maxmemory-samples进行设置 # # maxmemory-samples 3 ############################## AOF ############################### # 默认情况下,redis会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失。 # 所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式。 # 开启append only模式之后,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态。 # 但是这样会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令,对appendonly.aof 进行重新整理。 # 你可以同时开启asynchronous dumps 和 AOF appendonly no # AOF文件名称 (默认: "appendonly.aof") # appendfilename appendonly.aof # Redis支持三种同步AOF文件的策略: # # no: 不进行同步,系统去操作 . Faster. # always: always表示每次有写操作都进行同步. Slow, Safest. # everysec: 表示对写操作进行累积,每秒同步一次. Compromise. # # 默认是"everysec",按照速度和安全折中这是最好的。 # 如果想让Redis能更高效的运行,你也可以设置为"no",让操作系统决定什么时候去执行 # 或者相反想让数据更安全你也可以设置为"always" # # 如果不确定就用 "everysec". # appendfsync always appendfsync everysec # appendfsync no # AOF策略设置为always或者everysec时,后台处理进程(后台保存或者AOF日志重写)会执行大量的I/O操作 # 在某些Linux配置中会阻止过长的fsync()请求。注意现在没有任何修复,即使fsync在另外一个线程进行处理 # # 为了减缓这个问题,可以设置下面这个参数no-appendfsync-on-rewrite # # This means that while another child is saving the durability of Redis is # the same as "appendfsync none", that in pratical terms means that it is # possible to lost up to 30 seconds of log in the worst scenario (with the # default Linux settings). # # If you have latency problems turn this to "yes". Otherwise leave it as # "no" that is the safest pick from the point of view of durability. no-appendfsync-on-rewrite no # Automatic rewrite of the append only file. # AOF 自动重写 # 当AOF文件增长到一定大小的时候Redis能够调用 BGREWRITEAOF 对日志文件进行重写 # # 它是这样工作的:Redis会记住上次进行些日志后文件的大小(如果从开机以来还没进行过重写,那日子大小在开机的时候确定) # # 基础大小会同现在的大小进行比较。如果现在的大小比基础大小大制定的百分比,重写功能将启动 # 同时需要指定一个最小大小用于AOF重写,这个用于阻止即使文件很小但是增长幅度很大也去重写AOF文件的情况 # 设置 percentage 为0就关闭这个特性 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb ################################## SLOW LOG ################################### # Redis Slow Log 记录超过特定执行时间的命令。执行时间不包括I/O计算比如连接客户端,返回结果等,只是命令执行时间 # # 可以通过两个参数设置slow log:一个是告诉Redis执行超过多少时间被记录的参数slowlog-log-slower-than(微妙), # 另一个是slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除 # 下面的时间以微妙微单位,因此1000000代表一分钟。 # 注意制定一个负数将关闭慢日志,而设置为0将强制每个命令都会记录 slowlog-log-slower-than 10000 # 对日志长度没有限制,只是要注意它会消耗内存 # 可以通过 SLOWLOG RESET 回收被慢日志消耗的内存 slowlog-max-len 1024 ################################ VM ############################### ### WARNING! Virtual Memory is deprecated in Redis 2.4 ### The use of Virtual Memory is strongly discouraged. # Virtual Memory allows Redis to work with datasets bigger than the actual # amount of RAM needed to hold the whole dataset in memory. # In order to do so very used keys are taken in memory while the other keys # are swapped into a swap file, similarly to what operating systems do # with memory pages. # # To enable VM just set 'vm-enabled' to yes, and set the following three # VM parameters accordingly to your needs. vm-enabled no # vm-enabled yes # This is the path of the Redis swap file. As you can guess, swap files # can't be shared by different Redis instances, so make sure to use a swap # file for every redis process you are running. Redis will complain if the # swap file is already in use. # # The best kind of storage for the Redis swap file (that's accessed at random) # is a Solid State Disk (SSD). # # *** WARNING *** if you are using a shared hosting the default of putting # the swap file under /tmp is not secure. Create a dir with access granted # only to Redis user and configure Redis to create the swap file there. vm-swap-file /tmp/redis.swap # vm-max-memory configures the VM to use at max the specified amount of # RAM. Everything that deos not fit will be swapped on disk *if* possible, that # is, if there is still enough contiguous space in the swap file. # # With vm-max-memory 0 the system will swap everything it can. Not a good # default, just specify the max amount of RAM you can in bytes, but it's # better to leave some margin. For instance specify an amount of RAM # that's more or less between 60 and 80% of your free RAM. vm-max-memory 0 # Redis swap files is split into pages. An object can be saved using multiple # contiguous pages, but pages can't be shared between different objects. # So if your page is too big, small objects swapped out on disk will waste # a lot of space. If you page is too small, there is less space in the swap # file (assuming you configured the same number of total swap file pages). # # If you use a lot of small objects, use a page size of 64 or 32 bytes. # If you use a lot of big objects, use a bigger page size. # If unsure, use the default :) vm-page-size 32 # Number of total memory pages in the swap file. # Given that the page table (a bitmap of free/used pages) is taken in memory, # every 8 pages on disk will consume 1 byte of RAM. # # The total swap size is vm-page-size * vm-pages # # With the default of 32-bytes memory pages and 134217728 pages Redis will # use a 4 GB swap file, that will use 16 MB of RAM for the page table. # # It's better to use the smallest acceptable value for your application, # but the default is large in order to work in most conditions. vm-pages 134217728 # Max number of VM I/O threads running at the same time. # This threads are used to read/write data from/to swap file, since they # also encode and decode objects from disk to memory or the reverse, a bigger # number of threads can help with big objects even if they can't help with # I/O itself as the physical device may not be able to couple with many # reads/writes operations at the same time. # # The special value of 0 turn off threaded I/O and enables the blocking # Virtual Memory implementation. vm-max-threads 4 ############################### ADVANCED CONFIG ############################### # 当hash中包含超过指定元素个数并且最大的元素没有超过临界时, # hash将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值 # Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现, # 这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap, # 当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。 hash-max-zipmap-entries 512 hash-max-zipmap-value 64 # list数据类型多少节点以下会采用去指针的紧凑存储格式。 # list数据类型节点值大小小于多少字节会采用紧凑存储格式。 list-max-ziplist-entries 512 list-max-ziplist-value 64 # set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。 set-max-intset-entries 512 # zsort数据类型多少节点以下会采用去指针的紧凑存储格式。 # zsort数据类型节点值大小小于多少字节会采用紧凑存储格式。 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 # Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用 # # 当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。 # # 如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存 activerehashing yes ################################## INCLUDES ################################### # 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件 # include /path/to/local.conf # include /path/to/other.conf
启动slave从节点的redis服务
[root@master 192.168.119.10 ~]$redis-server /etc/redis-6380.conf [root@master 192.168.119.10 ~]$redis-server /etc/redis-6381.conf
验证从节点的redis服务
[root@master ~]$redis-cli -p 6380 ping PONG [root@master ~]$redis-cli -p 6381 ping PONG
确定主从关系
在主节点上查看主从通信关系
[root@master ~]# redis-cli -p 6379 info replication # Replication role:master connected_slaves:2 slave0:ip=192.168.119.10,port=6380,state=online,offset=407,lag=0 slave1:ip=192.168.119.10,port=6381,state=online,offset=407,lag=0 master_repl_offset:407 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:406
在从节点上查看主从关系(6380、6379)
[root@slave 192.168.119.11 ~]$redis-cli -p 6380 info replication # Replication role:slave master_host:192.168.119.10 master_port:6379 master_link_status:up master_last_io_seconds_ago:3 master_sync_in_progress:0 slave_repl_offset:505 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
此时可以在master上写入数据,在slave上查看数据,此时主从复制配置完成
开始配置Redis Sentinel
超哥实验的环境是单独一台linux,192.168.119.10
[root@master tmp]# ll /etc/redis-* -rw-r--r-- 1 root root 145 Nov 7 17:44 /etc/redis-6379.conf -rw-r--r-- 1 root root 93 Nov 7 17:42 /etc/redis-6380.conf -rw-r--r-- 1 root root 115 Nov 7 17:42 /etc/redis-6381.conf -rw-r--r-- 1 root root 556 Nov 7 17:42 /etc/redis-sentinel-26379.conf -rw-r--r-- 1 root root 556 Nov 7 17:42 /etc/redis-sentinel-26380.conf -rw-r--r-- 1 root root 556 Nov 7 17:42 /etc/redis-sentinel-26381.conf
redis-sentinel-26379.conf配置文件写入如下信息
// Sentinel节点的端口 port 26379 dir /var/redis/data/ logfile "26379.log" // 当前Sentinel节点监控 192.168.119.10:6379 这个主节点 // 2代表判断主节点失败至少需要2个Sentinel节点节点同意 // mymaster是主节点的别名 sentinel monitor mymaster 192.168.119.10 6379 2 //每个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
redis-sentinel-26380.conf和redis-sentinel-26381.conf的配置仅仅差异是port(端口)的不同。
然后启动三个sentinel哨兵
redis-sentinel /etc/redis-sentinel-26379.conf redis-sentinel /etc/redis-sentinel-26380.conf redis-sentinel /etc/redis-sentinel-26381.conf
监控拓扑图
此时查看哨兵是否成功通信
[root@master ~]# redis-cli -p 26379 info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=192.168.119.10:6379,slaves=2,sentinels=3
#看到最后一条信息正确即成功了哨兵,哨兵主节点名字叫做mymaster,状态ok,监控地址是192.168.119.10:6379,有两个从节点,3个哨兵
redis高可用故障实验
大致思路
- 杀掉主节点的redis进程6379端口,观察从节点是否会进行新的master选举,进行切换
- 重新恢复旧的“master”节点,查看此时的redis身份
首先查看三个redis的进程状态
ps -ef|grep redis
检查三个节点的复制身份状态
第一个
[root@master tmp]# redis-cli -p 6381 info replication # Replication role:slave master_host:127.0.0.1 master_port:6380
第二个
[root@master tmp]# redis-cli -p 6380 info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6381,state=online,offset=54386,lag=0 slave1:ip=127.0.0.1,port=6379,state=online,offset=54253,lag=0
第三个
[root@master tmp]# redis-cli -p 6379 info replication # Replication role:slave master_host:127.0.0.1 master_port:6380
此时,干掉master!!!然后等待其他两个节点是否能自动被哨兵sentienl,切换为master节点
ps -ef|grep 6380 #干掉master进程
此时查看两个slave的状态
精髓就是查看一个参数
master_link_down_since_seconds:13
稍等片刻之后,发现slave节点成为master节点!!
[root@master tmp]# redis-cli -p 6379 info replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6381,state=online,offset=41814,lag=1
大功告成!!开心!!!
redis-cluster配置
为什么要用redis-cluster
1.并发问题
redis官方生成可以达到 10万/每秒,每秒执行10万条命令
假如业务需要每秒100万的命令执行呢?
2.数据量太大
一台服务器内存正常是16~256G,假如你的业务需要500G内存,
新浪微博作为世界上最大的redis存储,就超过1TB的数据,去哪买这么大的内存条?各大公司有自己的解决方案,推出各自的集群功能,核心思想都是将数据分片(sharding)存储在多个redis实例中,每一片就是一个redis实例。
各大企业集群方案:
twemproxy由Twitter开源
Codis由豌豆荚开发,基于GO和C开发
redis-cluster官方3.0版本后的集群方案
解决方案如下
- 配置一个超级牛逼的计算机,超大内存,超强cpu,但是问题是。。。。
2.正确的应该是考虑分布式,加机器,把数据分到不同的位置,分摊集中式的压力,一堆机器做一件事
客户端分片
redis3.0集群采用P2P模式,完全去中心化,将redis所有的key分成了16384个槽位,每个redis实例负责一部分slot,集群中的所有信息通过节点数据交换而更新。
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-cluster集群架构
多个服务端,负责读写,彼此通信,redis指定了16384个槽。
多匹马儿,负责运输数据,马儿分配16384个槽位,管理数据。
ruby的脚本自动就把分配槽位这事做了
安装方式
官方提供通过ruby语言的脚本一键安装
1.环境准备
通过配置,开启redis-cluster
port 7000 daemonize yes dir "/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]#ls redis-7000.conf redis-7002.conf redis-7004.conf redis-7001.conf redis-7003.conf redis-7005.conf
#确保每个配置文件中的端口修改!!
2.运行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
检查日志文件
cat 7000.log
检查redis服务的端口、进程
netstat -tunlp|grep redis
ps -ef|grep redis
此时集群还不可用,可以通过登录redis查看
redis-cli -p 7000 set hello world (error)CLUSTERDOWN The cluster is down
3.创建开启redis-cluster
准备ruby环境
- 下载、编译、安装Ruby
- 安装rubygem redis
- 安装redis-trib.rb命令
第一步,安装ruby(这些命令可以放入一个sh脚本文件里)
#下载ruby wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz #安装ruby tar -xvf ruby-2.3.1.tar.gz ./configure --prefix=/opt/ruby/ make && make install
#准备一个ruby命令
#准备一个gem软件包管理命令 #拷贝ruby命令到path下/usr/local/ruby cp /opt/ruby/bin/ruby /usr/local/
cp bin/gem /usr/local/bin
安装ruby gem 包管理工具
wget http://rubygems.org/downloads/redis-3.3.0.gem gem install -l redis-3.3.0.gem
#查看gem有哪些包 gem list -- check redis 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 1
redis-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
安装完毕后,检查集群状态
[root@yugo /opt/redis/src 18:42:14]#redis-cli -p 7000 cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:10468 cluster_stats_messages_pong_sent:10558 cluster_stats_messages_sent:21026 cluster_stats_messages_ping_received:10553 cluster_stats_messages_pong_received:10468 cluster_stats_messages_meet_received:5 cluster_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 OK 127.0.0.1:7001> exit [root@yugo /opt/redis/src 18:46:07]#redis-cli -c -p 7000 127.0.0.1:7000> ping PONG 127.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"
集群ok
工作原理:
redis客户端任意访问一个redis实例,如果数据不在该实例中,通过重定向引导客户端访问所需要的redis实例
python操作redis集群
strictRedis对象方法用于连接redis
指定主机地址,port与服务器连接,默认db是0,redis默认数据库有16个,在配置文件中指定database 16
上代码
1、对redis的单实例进行连接操作
根据不同的实例方法,与redis的命令对应
python3 >>>import redis >>>r = redis.StrictRedis(host='localhost', port=6379, db=0,password='root') >>>r.set('lufei', 'guojialei') True >>>r.get('lufei') 'bar'
增删改查
>>> conn=redis.StrictRedis()
>>>
>>>
>>> conn.set("name1","alex1")
True
>>> conn.set("name2","wupeiqi")
True
>>>
>>>
>>> conn.set("name1","alex666")
True
>>> conn.delete("name2","name1")
2
>>> conn.keys()
[b'name3', b'name2', b'name1']
-------------------- 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-cluster 3、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' ----------------------
redis存储session
django-redis-sessions 官方文档:https://pypi.org/project/django-redis-sessions/
dango-redis 官方文档:http://niwinz.github.io/django-redis/latest/#_configure_as_cache_backend
安装模块
安装模块 pip3 install django-redis-sessions
或者
pip3 install django-redis
本文这里用的是django 2.0语法,创建django项目
django-admin startproject mydjango
修改settings.py文件
写入
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/0", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "PASSWORD": "", # "PARSER_CLASS": "redis.connection.HiredisParser", # "SOCKET_TIMEOUT": 10, # "CONNECTION_POOL_CLASS_KWARGS": { # "max_connections": 2, # } } } } #SESSION_COOKIE_AGE = 30 * 60 #设置session过期时间为30分钟 SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
创建app01
django-admin startapp app01
编写session视图函数 app01.views
from django.shortcuts import render,HttpResponse def set_session(request): request.session['username']='chaoge' request.session['age']=18 return HttpResponse("设置sesson成功") def get_session(request): username=request.session['username'] age = request.session['age'] return HttpResponse(username+":"+str(age))
添加url路由
vim mydjango/urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('set_session/',views.set_session), path('get_session/',views.get_session), path('admin/', admin.site.urls), ]
确保启动redis服务端,默认方式启动
redis-server &
redis-cli 连接无误
发送ping命令得到pong即可
启动django
python3 manage.py runserver 0.0.0.0:8000
访问视图,设置一条session信息,存入redis数据库
访问视图,获取session信息
检查redis数据库,是否存在一条key
127.0.0.1:6379> keys * 1) ":1:django.contrib.sessions.cachep220moqvxclz2hyjqmbybqs3v8ck2i39"
获取这个key的值
127.0.0.1:6379> get :1:django.contrib.sessions.cachep220moqvxclz2hyjqmbybqs3v8ck2i39
"\x80\x04\x95!\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\busername\x94\x8c\x06chaoge\x94\x8c\x03age\x94K\x12u."
redis面试题
redis和memcached比较?
redis中数据库默认是多少个db 及作用?
python操作redis的模块?
如果redis中的某个列表中的数据量非常大,如果实现循环显示每一个值?
redis如何实现主从复制?以及数据同步机制?
redis中的sentinel的作用?
如何实现redis集群?
redis中默认有多少个哈希槽?
简述redis的有哪几种持久化策略及比较?
列举redis支持的过期策略。
MySQL 里有 2000w 数据,redis 中只存 20w 的数据,如何保证 redis 中都是热点数据?
写代码,基于redis的列表实现 先进先出、后进先出队列、优先级队列。
如何基于redis实现消息队列?
如何基于redis实现发布和订阅?以及发布订阅和消息队列的区别?
什么是codis及作用?
什么是twemproxy及作用?
写代码实现redis事务操作。
redis中的watch的命令的作用?
基于redis如何实现商城商品数量计数器?
简述redis分布式锁和redlock的实现机制。
什么是一致性哈希?Python中是否有相应模块?
如何高效的找到redis中所有以oldboy开头的key?