转自: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中的数据(亲自测试)】的更多相关文章

  1. 向Android模拟器中批量导入通讯录联系人

    使用adb命令向Android模拟器中批量导入通讯录联系人的方法: 使用adb提供的命令, 可以非常方便地从PC中将通讯录批量导入android模拟器中. 首先要先准备好固定格式的vcf文件, 该文件 ...

  2. 用命令从mysql中导出/导入表结构及数据

    在命令行下mysql的数据导出有个很好用命令mysqldump,它的参数有一大把,可以这样查看:mysqldump最常用的:mysqldump -uroot -pmysql databasefoo t ...

  3. SpringMVC文件上传 Excle文件 Poi解析 验证 去重 并批量导入 MYSQL数据库

    SpringMVC文件上传 Excle文件 Poi解析并批量导入 MYSQL数据库  /** * 业务需求说明: * 1 批量导入成员 并且 自主创建账号 * 2 校验数据格式 且 重复导入提示 已被 ...

  4. Weka里如何将arff文件或csv文件批量导入MySQL数据库(六)

    这里不多说,直接上干货! 前提博客是 Weka中数据挖掘与机器学习系列之数据格式ARFF和CSV文件格式之间的转换(四) 1.将arff文件批量导入MySQL数据库 我在这里,arff文件以Weka安 ...

  5. MySQL批量导入Excel、txt数据

    MySQL批量导入Excel.txt数据 我想Excel是当今最大众化的批量数据管理软件了吧,所以我们会经常涉及到将Excel中数据导入到MySQL中的工作.网上有一些关于直接将Excel导入MySQ ...

  6. .net core利用MySqlBulkLoader大数据批量导入MySQL

    最近用core写了一个数据迁移小工具,从SQLServer读取数据,加工后导入MySQL,由于数据量太过庞大,数据表都过百万,常用的dapper已经无法满足.三大数据库都有自己的大数据批量导入数据的方 ...

  7. My SQL中show命令--MySQL中帮助查看

    My SQL中show命令--MySQL中帮助查看 学习了:http://hahaxiao.techweb.com.cn/archives/477.html 在mysql命令界面内,输入help或者? ...

  8. PHP如何批量更新MYSQL中的数据

    最近项目需要用到批量更新数据库里的数据,在网上找了一下这方面的例子,觉得这个还不错,分享给大家. 在这个业务里里面涉及到了更新两张数据表,那么大家是不是会想到非常简单,马上上代码 $sql ,type ...

  9. PHP批量更新MYSQL中的数据

    原文链接:https://blog.csdn.net/wuming19900801/article/details/62893429 $sql = "update newhouse_clic ...

随机推荐

  1. Java写学生管理系统

    package Homework08;/*调试了一上午,收获:学会了昨天的debug的使用吸取教训:Student stus[]=new Student[2]; for (int i=0;i<s ...

  2. python 画3D的高斯曲线

    用python画3D的高斯曲线,我想如果有多个峰怎么画? import numpy as npimport matplotlib.pyplot as pltimport mathimport mpl_ ...

  3. codeblocks 使用汇总

    codeblocks 使用汇总 http://www.cnblogs.com/-clq/archive/2012/01/31/2333247.html

  4. JS-完数

    完数 完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数.它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身.如果一个数恰好等于它的因子之和,则称该数 ...

  5. 2.IOC 配置与应用(xml的方式)

    1.注入方式 a)setter(主要) b)构造方法(可以忘记) c)接口注入(可以忘记) 2.id  vs  name bean 标签中可以使用  name 属性 来完成 id 属性的功能,不过习惯 ...

  6. Spring Cloud(六)服务网关 zuul 快速入门

    服务网关是微服务架构中一个不可或缺的部分.通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由.均衡负载功能之外,它还具备了权限控制等功能.Spring Cloud Netflix中 ...

  7. 13_Redis_持久化

    一:概述: Redis的高性能是山于其将所有数据都存储在了内存中,为了使Redis在重启之后仍能保证数据不丢失,需要将数据从内存中同步到硬盘中,这一过程就是持久化. Redis支持两种方式的持久化,一 ...

  8. Linux date cal bc和一些快捷键学习

    1 date 日期   2 cal 日历 具体每年日历  cal +年份 3 bc 计算器  如果有小数点需要scale命令,scale=数字 quit退出   4 [Tab]按键 :命令补全和档案补 ...

  9. shell变量引用

    var="www.sina.com.cn" echo ${var#*.} #sina.com.cn 从前向后删 echo ${var##*.} #.cn 贪婪模式从前向后删 ech ...

  10. map()函数浅析

    MapReduce的设计灵感来自于函数式编程,这里不打算提MapReduce,就拿python中的map()函数来学习一下. 文档中的介绍在这里: map(function, iterable, .. ...