【Redis 向Redis中批量导入mysql中的数据(亲自测试)】
转自:https://blog.csdn.net/kenianni/article/details/84910638 有改动,仅供个人学习
问题提出:缓存的冷启动问题
应用系统新版本上线,这时候 redis cluster 集群内存中可能没有数据的,这时候大量请求进去,会导致大量的高并发请求和流量直接打到mysql 中,完蛋,mysql 挂了,redis cluster 集群中也没有数据,这时候整个系统就处于不可用状态;应用系统运行过程中,突然 redis cluster 集群挂了,内存中数据也没有了,就算开启了持久化也无法恢复数据,然后集群在故障中重新启动,这时候全部请求同样进入mysql,mysql 也搞挂了,系统同样出于不可用状态。
从上面两点看,不管如何,只要redis cluster 集群内存中没有数据,那么大量请求进来,都有可能导致mysql崩溃,从而系统不可以用。
redis cluster 集群启动,没有任何的缓存数据,可以称之为redis缓存冷启动。
缓存冷启动,redis cluster启动后,没有任何数据,就直接对外提供服务了,这是mysql 就相当于裸奔状态。解决冷启动的方案是数据预热:
解决方案思路
redis 启动后,提前给redis 灌入部分数据,然后再给应用提供服务部分数据指的是根据当天具体的访问情况,进行时时统计出访问频率较高的数据(热数据),因为我们不可能将所有数据写入redis,数据量大,灌入数据时间消耗长,而且也没必要热数据会比较多,这时候我们需要多个服务并行进行读写(并行的分布式缓存预热)完成以上数据预热,然后提供对外服务,这样就不会存在redis 冷启动了,从而减少了大部分数据的 mysql 读压力。
举例场景:存储游戏玩家的任务数据,游戏服务器启动时将mysql中玩家的数据同步到redis中。
从MySQL中将数据导入到Redis的Hash结构中。当然,最直接的做法就是遍历MySQL数据,一条一条写入到Redis中。这样没什么错,但是速度会非常慢。如果能够想法使得MySQL的查询输出数据直接能够与Redis命令行的输入数据协议相吻合,可以节省很多消耗和缩短时间。
Mysql数据库名称为:GAME_DB, 表结构举例:
CREATE TABLE TABLE_MISSION (
playerId int(11) unsigned NOT NULL,
missionList varchar(255) NOT NULL,
PRIMARY KEY (playerId)
);
Redis中的数据结构使用哈希表:
键KEY为mission, 哈希域为mysql中对应的playerId, 哈希值为mysql中对应的missionList。 数据如下:
[root@iZ23zcsdouzZ ~]# redis-cli
127.0.0.1:6379> hget missions 36598
"{\"10001\":{\"status\":1,\"progress\":0},\"10002\":{\"status\":1,\"progress\":0},\"10003\":{\"status\":1,\"progress\":0},\"10004\":{\"status\":1,\"progress\":0}}"
快速同步方法:
新建一个后缀.sql文件:mission.sql内容如下:
SELECT CONCAT(
"*4\r\n",
'$', LENGTH(redis_cmd), '\r\n',
redis_cmd, '\r\n',
'$', LENGTH(redis_key), '\r\n',
redis_key, '\r\n',
'$', LENGTH(hkey), '\r\n',
hkey, '\r\n',
'$', LENGTH(hval), '\r\n',
hval, '\r'
)
FROM (
SELECT
'HSET' as redis_cmd,
'missions' AS redis_key,
playerId AS hkey,
missionList AS hval
FROM TABLE_MISSION
) AS t
保存退出,在命令行执行命令(或写成一个shell脚本):
mysql GAME_DB --skip-column-names --raw < mission.sql | redis-cli --pipe
上述命令中参数说明:
很重要的mysql参数说明:
--raw: 使mysql不转换字段值中的换行符。
--skip-column-names: 使mysql输出的每行中不包含列名。
数据库中有7条数据,测试成功输出:
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 7
Linux系统终端执行命令后,将mysql数据库GAME_DB的表TABLE_MISSION数据同步到redis中键missions中去。mission.sql文件就是将mysql数据的输出数据格式和redis的输入数据格式协议相匹配,从而大大缩短了同步时间。
经过测试,同样一份数据通过单条取出修改数据格式同步写入到redis消耗的时间为5min, 使用上面的sql文件和shell命令,同步完数据仅耗时3s左右。
关于以上的补充:
1、mysql配置root用户免密登录:
执行命令:
mysql GAME_DB --skip-column-names --raw < mission.sql | redis-cli --pipe
需要使得mysql处于免密码登录的状态,否则会报如下的错:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
具体的配置mysql免密的方式有常用的2种:
【方法1】
cd到root用户家目录下 创建 .my.cnf 的文件后vim进行编辑
普通用户则是/home目录下创建
输入命令
vim .my.cnf
然后在文件中输入下面的命令
[client]
host=localhost
user="root" #如是普通用户输入用户名即可
password="******" #这里填入你的mysql root(普通用户)用户对应的密码
保存退出后 重新启动MySQL数据库即可
systemctl restart mysqld
root用户直接输入 mysql即可登陆mysql数据库
普通用户输入 show mysql
【方法2】(测试)
进入到mysql数据库的配置文件当中 vim /etc/my.cnf
在[mysqld]的段中加上一句:skip-grant-tables
例如:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
skip-name-resolve
skip-grant-tables
保存并且退出vim
重新启动mysql数据库即可
2、可以使用命令而非免密登录的方式执行shell命令:
mysql -h host -uroot -p123456 test --default-character-set=utf8 --skip-column-names --raw < /usr/redis/order.sql | /usr/redis/redis-cli -h host -p 6379 -a 123456 --pipe #-h host -uroot -p123456 test 分别为:mysql远程地址,用户名,密码,数据库名
#/usr/redis/order.sql | /usr/redis/redis-cli 分别为sql文件和redis客户端文件目录的地址
#-h host -p 6379 -a 123456 分别为redis远程地址,端口,密码
或者
mysql -uroot -proot -Dxfdb --default-character-set=utf8 --skip-column-names --raw < mysql_to_redis.sql | redis-cli -h 127.0.0.1 --pipe
3、编写sql脚本的编码问题:
如果直接复制上述sql脚本中的内容到linux终端的vim中,可能会报错,如下:
ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'oSELECT CONCAT(
"*4\r\n",
'$', LENGTH(redis_cmd), '\r\n',
redis_cmd, '\r\n' at line 1
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 0
此时,可以先将sql脚本内容复制到文本编辑器中(例如sublime),然后再复制到vim中。
【Redis 向Redis中批量导入mysql中的数据(亲自测试)】的更多相关文章
- 向Android模拟器中批量导入通讯录联系人
使用adb命令向Android模拟器中批量导入通讯录联系人的方法: 使用adb提供的命令, 可以非常方便地从PC中将通讯录批量导入android模拟器中. 首先要先准备好固定格式的vcf文件, 该文件 ...
- 用命令从mysql中导出/导入表结构及数据
在命令行下mysql的数据导出有个很好用命令mysqldump,它的参数有一大把,可以这样查看:mysqldump最常用的:mysqldump -uroot -pmysql databasefoo t ...
- SpringMVC文件上传 Excle文件 Poi解析 验证 去重 并批量导入 MYSQL数据库
SpringMVC文件上传 Excle文件 Poi解析并批量导入 MYSQL数据库 /** * 业务需求说明: * 1 批量导入成员 并且 自主创建账号 * 2 校验数据格式 且 重复导入提示 已被 ...
- Weka里如何将arff文件或csv文件批量导入MySQL数据库(六)
这里不多说,直接上干货! 前提博客是 Weka中数据挖掘与机器学习系列之数据格式ARFF和CSV文件格式之间的转换(四) 1.将arff文件批量导入MySQL数据库 我在这里,arff文件以Weka安 ...
- MySQL批量导入Excel、txt数据
MySQL批量导入Excel.txt数据 我想Excel是当今最大众化的批量数据管理软件了吧,所以我们会经常涉及到将Excel中数据导入到MySQL中的工作.网上有一些关于直接将Excel导入MySQ ...
- .net core利用MySqlBulkLoader大数据批量导入MySQL
最近用core写了一个数据迁移小工具,从SQLServer读取数据,加工后导入MySQL,由于数据量太过庞大,数据表都过百万,常用的dapper已经无法满足.三大数据库都有自己的大数据批量导入数据的方 ...
- My SQL中show命令--MySQL中帮助查看
My SQL中show命令--MySQL中帮助查看 学习了:http://hahaxiao.techweb.com.cn/archives/477.html 在mysql命令界面内,输入help或者? ...
- PHP如何批量更新MYSQL中的数据
最近项目需要用到批量更新数据库里的数据,在网上找了一下这方面的例子,觉得这个还不错,分享给大家. 在这个业务里里面涉及到了更新两张数据表,那么大家是不是会想到非常简单,马上上代码 $sql ,type ...
- PHP批量更新MYSQL中的数据
原文链接:https://blog.csdn.net/wuming19900801/article/details/62893429 $sql = "update newhouse_clic ...
随机推荐
- Java写学生管理系统
package Homework08;/*调试了一上午,收获:学会了昨天的debug的使用吸取教训:Student stus[]=new Student[2]; for (int i=0;i<s ...
- python 画3D的高斯曲线
用python画3D的高斯曲线,我想如果有多个峰怎么画? import numpy as npimport matplotlib.pyplot as pltimport mathimport mpl_ ...
- codeblocks 使用汇总
codeblocks 使用汇总 http://www.cnblogs.com/-clq/archive/2012/01/31/2333247.html
- JS-完数
完数 完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数.它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身.如果一个数恰好等于它的因子之和,则称该数 ...
- 2.IOC 配置与应用(xml的方式)
1.注入方式 a)setter(主要) b)构造方法(可以忘记) c)接口注入(可以忘记) 2.id vs name bean 标签中可以使用 name 属性 来完成 id 属性的功能,不过习惯 ...
- Spring Cloud(六)服务网关 zuul 快速入门
服务网关是微服务架构中一个不可或缺的部分.通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由.均衡负载功能之外,它还具备了权限控制等功能.Spring Cloud Netflix中 ...
- 13_Redis_持久化
一:概述: Redis的高性能是山于其将所有数据都存储在了内存中,为了使Redis在重启之后仍能保证数据不丢失,需要将数据从内存中同步到硬盘中,这一过程就是持久化. Redis支持两种方式的持久化,一 ...
- Linux date cal bc和一些快捷键学习
1 date 日期 2 cal 日历 具体每年日历 cal +年份 3 bc 计算器 如果有小数点需要scale命令,scale=数字 quit退出 4 [Tab]按键 :命令补全和档案补 ...
- shell变量引用
var="www.sina.com.cn" echo ${var#*.} #sina.com.cn 从前向后删 echo ${var##*.} #.cn 贪婪模式从前向后删 ech ...
- map()函数浅析
MapReduce的设计灵感来自于函数式编程,这里不打算提MapReduce,就拿python中的map()函数来学习一下. 文档中的介绍在这里: map(function, iterable, .. ...