1. Redis集群方案
常见Redis集群4种方案:
官方cluster方案
哨兵模式
codis
客户端分片
(1)官方cluser方案
从redis 3.0版本开始支持redis-cluster集群,redis-cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他节点连接。redis-cluster是一种服务端分片技术。但现在为了安全,不建议用reids6.0以下版本了。
redis-cluster架构图
redis-cluster特点:
每个节点都和n-1个节点通信,这被称为集群总线(cluster bus)。它们使用特殊的端口号,即对外服务端口号加10000。所以要维护好这个集群的每个节点信息,不然会导致整个集群不可用,其内部采用特殊的二进制协议优化传输速度和带宽。
redis-cluster把所有的物理节点映射到[0,16383]slot(槽)上,cluster负责维护node–slot–value。
集群预分好16384个桶,当需要在redis集群中插入数据时,根据CRC16(KEY) mod 16384的值,决定将一个key放到哪个桶中。
客户端与redis节点直连,不需要连接集群所有的节点,连接集群中任何一个可用节点即可。
redis-trib.rb脚本(rub语言)为集群的管理工具,比如自动添加节点,规划槽位,迁移数据等一系列操作。
节点的fail是通过集群中超过半数的节点检测失效时才生效。
整个cluster被看做是一个整体,客户端可连接任意一个节点进行操作,当客户端操作的key没有分配在该节点上时,redis会返回转向指令,指向正确的节点。
为了增加集群的可访问性,官方推荐的方案是将node配置成主从结构,即一个master主节点,挂n个slave从节点。如果主节点失效,redis cluster会根据选举算法从slave节点中选择一个上升为master节点,整个集群继续对外提供服务。
(2)哨兵模式
Sentinel(哨兵)是Redis的高可用性解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器以及这些主服务器下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。
哨兵模式架构图
Sentinel的工作方式
每个Sentinel以每秒钟一次的频率向它所知的Master、Slave以及其他Sentinel实例发送一个PING命令。
如果一个实例距离最后一次有效回复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的主观下线状态就会被移除。
(3) codis
codis是一个分布式的Redis解决方案,由豌豆荚开源,对于上层的应用来说,连接codis proxy和连接原生的redis server没什么明显的区别,上层应用可以像使用单机的redis一样使用,codis底层会处理请求的转发,不停机的数据迁移等工作,所有后边的事情,对于前面的客户端来说是透明的,可以简单的认为后边连接的是一个内存无限大的redis服务。
codis架构图
(4)客户端分片
客户端就已经决定数据会被 存储 到哪个 redis 节点或者从哪个 redis 节点 读取数据。其主要思想是采用 哈希算法 将 Redis 数据的 key 进行散列,通过 hash 函数,特定的 key会 映射 到特定的 Redis 节点上。这种方案通常适用于用户对客户端的行为有完全控制能力的场景。
客户端分片 架构图
优点
不使用 第三方中间件,分区逻辑 可控,配置 简单,节点之间无关联,容易 线性扩展,灵活性强。
缺点
客户端 无法 动态增删 服务节点,客户端需要自行维护 分发逻辑,客户端之间 无连接共享,会造成 连接浪费。
2.mysql与redis怎么结合使用
一、将mysql表同步到redis
例如:将mysql的demo库中的stu表装载到redis中
步骤
使用mysql的sql语句生成准备导入的数据,将要导入的数据生成带有redis命令的结果集
将产生结果集的sql语句保存到文本文件中
利用mysql客户端运行sql语句脚本,将产生的结果集交给redis客户端,然后装载数据到redis中
SQL语句测试结果集
mysql> select concat(‘hmset stu:’,sno,’ sno ‘,sno,’ sname ‘,sname,’ sex ‘,sex,’ birth ‘,birth,’ height ‘,height,’ weight ‘,weight,’ score ‘,score,’ cno ',ifnull(cno,‘null’)) from stu;
生成SQL语句脚本mysql2redis.sql
将mysql数据表stu装载到redis执行方式
# mysql -uroot -p demo --skip-column-names --raw < mysql2redis.sql | redis-cli --pipe
# mysql客户端选项
# -N, --skip-column-names Don’t write column names in results.
# -r, --raw Write fields without conversion.
# redis-cli客户端选项
# --pipe Transfer raw Redis protocol from stdin to server.
#mysql2redis.sql文件内容
select concat(‘hmset stu:’,sno,’ sno ‘,sno,’ sname ‘,sname,’ sex ‘,sex,’ birth ‘,birth,’ height ‘,height,’ weight ‘,weight,’ score ‘,score,’ cno ‘,ifnull(cno,‘null’)) from stu;
select concat(‘hmset class:’,cno,’ cno ‘,cno,’ cname ‘,cname,’ teacher ‘,teacher) from class;
select concat(‘hmset bmi:’,id,’ id ‘,id,’ bname ‘,bname,’ lval ‘,lval,’ hval ‘,hval,’ sex ',sex) from bmi;
导入数据到redis
mysql -uroot -p demo --skip-column-names --raw < mysql2redis.sql | redis-cli --pipe
二、Redis缓存MySQL的常用方案
写入数据时,分别写到redis和mysql中
读取数据时,先查看redis中是否已缓存,如果有之间从redis中读取,因为其高性能;如果没有应用程序从mysql中读取,返回给用户的同时把该数据缓存一份到redis中以备后用
三、使用python脚本
import pymysql
import redis
# 连接到MySQL
mysql_conn = pymysql.connect(host='localhost', user='your_user', password='your_password', db='your_db')
mysql_cursor = mysql_conn.cursor()
# 连接到Redis
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)
# 查询MySQL数据
mysql_cursor.execute("SELECT * FROM your_table")
rows = mysql_cursor.fetchall()
# 遍历每行数据,存入Redis
for row in rows:
# 假设每行数据对应Redis中的一个哈希
redis_key = 'your_key_prefix:' + str(row[0]) # 假设第一列是主键
redis_client.hmset(redis_key, dict(zip(["field{}".format(i) for i in range(1, len(row))], row)))
# 关闭MySQL和Redis连接
mysql_cursor.close()
mysql_conn.close()