对于高频/大流量访问的数据接口,我们都会使用缓存进行优化,从而减少对数据库的连接压力及加快接口数据的返回,从而达到一定的性能优化
这里我们使用 MySQL 和 Redis 两个数据库进行对比
首先,我们先单独测试下,直接连接MySQL读取数据以及直接连接Redis读取数据的一个性能差距
说明:为了保证硬件性能差异的问题,我们的 MySQL 和 Redis 在同一台服务器中(4核4G)
MySQL使用EF6进行操作,Redis使用 RedisSQLHelper(基于StackExchange.Redis)
下面代码省略许多,看做伪代码即可
public string TestMysql() { var data = demo001Entities.Article.First(p => p.Id == 1); return ToJson(data); } public string TestRedis() { var data = redisHelper.StringGet("1"); return data; }
测试一:
我们使用 Apache 的 AB 压测工具进行分别压测(不过由于Demo中的SQL操作简单,所以差距并不明显,如果是较为复杂并且比较消耗时间和性能的SQL,明显会比较大)
ab -n 2000 -c 400 localhost:50493/home/TestMysql
TestMysql的
TestRedis的
测试二:
直接在程序内部进行多次调用
public string Index(int n) { //TestMysql DateTime mysqlStime = DateTime.Now; for (int i = 0; i < n; i++) { TestMysql(); } DateTime mysqlEtime = DateTime.Now; //TestRedis DateTime redisStime = DateTime.Now; for (int i = 0; i < n; i++) { TestRedis(); } DateTime redisEtime = DateTime.Now; string mysql = "mysql:" + (mysqlEtime - mysqlStime).TotalSeconds+"s"; string redis = "redis:" + (redisEtime - redisStime).TotalSeconds+"s"; return mysql + " | " + redis; }
100次
1000次
5000次
综上可以看出,使用 Redis 作为缓存中间件后,性能的提升还是可以相当明显的
接下来,我们用 .Net 的方式进行 Redis 缓存的实现,基本流程如下
public string Index(string n) { string result = "", comeFrom = ""; //判断缓存是否存在数据 var redisData = redisHelper.StringGet(n); if (redisData == null) { comeFrom = "mysql"; int id = Convert.ToInt32(n); result = ToJson(demo001Entities.Article.First(p => p.Id == id)); //写入缓存 redisHelper.StringSet(n, result); } else { comeFrom = "redis"; result = redisData; } return comeFrom + "|" + result; }
效果就是,首次获取数据的时候如果不存在,直接获取 MySQL 里面的数据进行返回,第二次获取相同的数据的时候,就会直接从 Redis 缓存中进行获取
第一次
第二次
以上是简单的实现方式,实际情况中,我们还需要思考 Redis 与数据库的数据同步问题,缓存失效时间(数据淘汰策略),缓存击穿,缓存雪崩等问题