游戏服务器使用MongoDB作为缓存数据库在服务器,还有必要使用Redis缓存吗

问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
mongodb做持久化存储数据库,还有必要使用redis再做一层缓存吗?
ps:我自己观察了一下mongodb服务端进程即使数据量很小(容量1g多)在运行的时候也占了有1g多内存,难道mongodb自己实现了一套将热数据放在内存的缓存?
来源: MongoDB 技术问答
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
redis做缓存只是为了让应用或网站访问加速,减少数据库压力,这才是缓存的目的.如果mongodb的访问速度正常,压力不大,那么就不需要使用缓存.
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你猜的没错,mongoDB 倾向于尽量把数据存储在内存中;压力不大可以不用 redis。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
难道mongodb自己实现了一套将热数据放在内存的缓存?
mongodb做持久化存储数据库,还有必要使用redis再做一层缓存吗?
如果你不觉得有必要,那就是没必要。对于 MongoDB,一般只有需要大量计算的内容才需要另外放缓存里去。
另外 Redis 不仅仅可以当缓存,也有很多其它用法。
同步到新浪微博
分享到微博?
你好!看起来你挺喜欢这个内容,但是你还没有注册帐号。 当你创建了帐号,我们能准确地追踪你关注的问题,在有新答案或内容的时候收到网页和邮件通知。还能直接向作者咨询更多细节。如果上面的内容有帮助,记得点赞 (????)? 表示感谢。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:基于C#的MongoDB数据库开发应用(4)--Redis的安装及使用 - 简书
基于C#的MongoDB数据库开发应用(4)--Redis的安装及使用
在前面介绍了三篇关于MongoDB数据库的开发使用文章,严格来讲这个不能归类于MongoDB数据库开发,不过Redis又有着和MongoDB数据库非常密切的关系,它们两者很接近,Redis主要是内存中的NoSQL数据库,用来提高性能的;MongoDB数据库则是文件中的NoSQL数据库,做数据序列号存储使用的,它们两者关系密切又有所区别。本篇主要介绍Redis的安装及使用,为后面Redis和MongoDB数据库的联合使用先铺下基础。
1、Redis基础及安装
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。Redis的代码遵循ANSI-C编写,可以在所有POSIX系统(如Linux, BSD, Mac OS X, Solaris等)上安装运行。而且Redis并不依赖任何非标准库,也没有编译参数必需添加。*1)Redis支持两种持久化方式:
(1):snapshotting(快照)也是默认方式.(把数据做一个备份,将数据存储到文件)
(2)Append-only file(缩写aof)的方式
快照是默认的持久化方式,这种方式是将内存中数据以快照的方式写到二进制文件中,默认的文件名称为dump.rdb.可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key键修改就自动做快照.
aof方式:由于快照方式是在一定间隔时间做一次的,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。aof比快照方式有更好的持久化性,是由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到文件中,当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
2)Redis数据结构Redis 的作者antirez曾称其为一个数据结构服务器(data structures server),这是一个非常准确的表述,Redis的所有功能就是将数据以其固有的几种结构保存,并提供给用户操作这几种结构的接口。我们可以想象我们在各种语言中的那些固有数据类型及其操作。Redis目前提供四种数据类型:string,list,set及zset(sorted set)和Hash。
string是最简单的类型,你可以理解成与Memcached一模一个的类型,一个key对应一个value,其上支持的操作与Memcached的操作类似。但它的功能更丰富。
list是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等。操作中key理解为链表的名字。
set是集合,和我们数学中的集合概念相似,对集合的操作有添加删除元素,有对多个集合求交并差等操作。操作中key理解为集合的名字。
zset是set的一个升级版本,他在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解了有两列的mysql表,一列存value,一列存顺序。操作中key理解为zset的名字。
Hash**数据类型允许用户用Redis存储对象类型,Hash数据类型的一个重要优点是,当你存储的数据对象只有很少几个key值时,数据存储的内存消耗会很小.更多关于Hash数据类型的说明请见:
3)Redis数据存储Redis的存储分为内存存储、磁盘存储和log文件三部分,配置文件中有三个参数对其进行配置。save seconds updates,save配置,指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。appendonly yes/no ,appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。appendfsync no/always/everysec ,appendfsync配置,no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次。
4)Redis的安装Redis可以在不同的平台运行,不过我主要基于Windows进行开发工作,所以下面主要是基于Windows平台进行介绍。Redis可以安装以DOS窗口启动的,也可以安装为Windows服务的,一般为了方便,我们更愿意把它安装为Windows服务,这样可以比较方便管理。下载地址:下载,安装为Windows服务即可。当前可以下载到最新的Windows安装版本为3.0,安装后作为Windows服务运行,安装后可以在系统的服务里面看到Redis的服务在运行了,如下图所示。
安装好Redis后,还有一个Redis伴侣Redis Desktop Manager需要安装,这样可以实时查看Redis缓存里面有哪些数据,具体地址如下:下载属于自己平台的版本即可
下载安装后,打开运行界面,如果我们往里面添加键值的数据,那么可以看到里面的数据了。
2、Redis的C#使用Redis目前提供四种数据类型:string,list,set及zset(sorted set)和Hash。因此它在C#里面也有对应的封装处理,而且有很多人对他进行了封装,提供了很多的响应开发包,具体可以访问 进行了解。一般建议用ServiceStack.Redis的封装驱动比较好,具体的使用可以参考。我们开发C#代码的时候,可以在NuGet程序包上面进行添加对应的ServiceStack.Redis引用,如下所示。
在弹出的NuGet程序包里面,输入ServiceStack.Redis进行搜索,并添加下面的驱动引用即可。
这样会在项目引用里面添加了几个对应的程序集,如下所示。
在C#里面使用Redis,首先需要实例化一个Redis的客户端类,如下所示。
//创建一个Redis的客户端类
RedisClient client = new RedisClient("127.0.0.1", 6379);
在使用前,我们需要清空所有的键值存储,使用FushAll方法即可,如下所示
//Redis FlushAll 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。
client.FlushAll();
根据上面的驱动,可以为不同类型的处理编写一些演示代码,下面代码是摘录网上的案例进行介绍。
#region string类型的测试代码
client.Add&string&("StringValueTime", "带有有效期的字符串", DateTime.Now.AddMilliseconds(10000));
while (true)
if (client.ContainsKey("StringValueTime"))
Console.WriteLine("String.键:StringValue, 值:{0} {1}", client.Get&string&("StringValueTime"), DateTime.Now);
Thread.Sleep(10000);
Console.WriteLine("键:StringValue, 值:已过期 {0}", DateTime.Now);
client.Add&string&("StringValue", " String和Memcached操作方法差不多");
Console.WriteLine("数据类型为:String.键:StringValue, 值:{0}", client.Get&string&("StringValue"));
Student stud = new Student() { id = "1001", name = "李四" };
client.Add&Student&("StringEntity", stud);
Student Get_stud = client.Get&Student&("StringEntity");
Console.WriteLine("数据类型为:String.键:StringEntity, 值:{0} {1}", Get_stud.id, Get_stud.name);
#endregion
#region Hash类型的测试代码
client.SetEntryInHash("HashID", "Name", "张三");
client.SetEntryInHash("HashID", "Age", "24");
client.SetEntryInHash("HashID", "Sex", "男");
client.SetEntryInHash("HashID", "Address", "上海市XX号XX室");
List&string& HaskKey = client.GetHashKeys("HashID");
foreach (string key in HaskKey)
Console.WriteLine("HashID--Key:{0}", key);
List&string& HaskValue = client.GetHashValues("HashID");
foreach (string value in HaskValue)
Console.WriteLine("HashID--Value:{0}", value);
List&string& AllKey = client.GetAllKeys(); //获取所有的key。
foreach (string Key in AllKey)
Console.WriteLine("AllKey--Key:{0}", Key);
#endregion
#region List类型的测试代码
* list是一个链表结构,主要功能是push,pop,获取一个范围的所有的值等,操作中key理解为链表名字。
* Redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素,
* 这样list既可以作为栈,又可以作为队列。Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,
* Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构
client.EnqueueItemOnList("QueueListId", "1.张三");
client.EnqueueItemOnList("QueueListId", "2.张四");
client.EnqueueItemOnList("QueueListId", "3.王五");
client.EnqueueItemOnList("QueueListId", "4.王麻子");
long q = client.GetListCount("QueueListId");
Console.WriteLine(client.GetItemFromList("QueueListId", 0));
for (int i = 0; i & i++)
Console.WriteLine("QueueListId出队值:{0}", client.DequeueItemFromList("QueueListId"));
//出队(队列先进先出)
q = client.GetListCount("QueueListId");
Console.WriteLine(q);
client.PushItemToList("StackListId", "1.张三");
client.PushItemToList("StackListId", "2.张四");
client.PushItemToList("StackListId", "3.王五");
client.PushItemToList("StackListId", "4.王麻子");
long p = client.GetListCount("StackListId");
for (int i = 0; i & i++)
Console.WriteLine("StackListId出栈值:{0}", client.PopItemFromList("StackListId"));
//出栈(栈先进后出)
q = client.GetListCount("StackListId");
Console.WriteLine(q);
#endregion
#region Set无序集合的测试代码
它是string类型的无序集合。set是通过hash table实现的,添加,删除和查找,对集合我们可以取并集,交集,差集
client.AddItemToSet("Set1001", "小A");
client.AddItemToSet("Set1001", "小B");
client.AddItemToSet("Set1001", "小C");
client.AddItemToSet("Set1001", "小D");
HashSet&string& hastsetA = client.GetAllItemsFromSet("Set1001");
foreach (string item in hastsetA)
Console.WriteLine("Set无序集合ValueA:{0}", item); //出来的结果是无须的
client.AddItemToSet("Set1002", "小K");
client.AddItemToSet("Set1002", "小C");
client.AddItemToSet("Set1002", "小A");
client.AddItemToSet("Set1002", "小J");
HashSet&string& hastsetB = client.GetAllItemsFromSet("Set1002");
foreach (string item in hastsetB)
Console.WriteLine("Set无序集合ValueB:{0}", item); //出来的结果是无须的
HashSet&string& hashUnion = client.GetUnionFromSets(new string[] { "Set1001", "Set1002" });
foreach (string item in hashUnion)
Console.WriteLine("求Set1001和Set1002的并集:{0}", item); //并集
HashSet&string& hashG = client.GetIntersectFromSets(new string[] { "Set1001", "Set1002" });
foreach (string item in hashG)
Console.WriteLine("求Set1001和Set1002的交集:{0}", item);
HashSet&string& hashD = client.GetDifferencesFromSet("Set1001", new string[] { "Set1002" });
//[返回存在于第一个集合,但是不存在于其他集合的数据。差集]
foreach (string item in hashD)
Console.WriteLine("求Set1001和Set1002的差集:{0}", item);
#endregion
SetSorted 有序集合的测试代码
sorted set 是set的一个升级版本,它在set的基础上增加了一个顺序的属性,这一属性在添加修改.元素的时候可以指定,
* 每次指定后,zset(表示有序集合)会自动重新按新的值调整顺序。可以理解为有列的表,一列存 value,一列存顺序。操作中key理解为zset的名字.
client.AddItemToSortedSet("SetSorted1001", "1.刘仔");
client.AddItemToSortedSet("SetSorted1001", "2.星仔");
client.AddItemToSortedSet("SetSorted1001", "3.猪仔");
List&string& listSetSorted = client.GetAllItemsFromSortedSet("SetSorted1001");
foreach (string item in listSetSorted)
Console.WriteLine("SetSorted有序集合{0}", item);
#endregion
对于具体类型的类对象,也可以使用As方法进行转换为对应的处理对象进行处理,如下所示
IRedisTypedClient&Phone& phones = client.As&Phone&();
具体的测试代码如下所示。
/// &summary&
/// Redis对对象类的处理例子
/// &/summary&
private void btnTypeValue_Click(object sender, EventArgs e)
IRedisTypedClient&Phone& phones = client.As&Phone&();
Phone phoneFive = phones.GetValue("5");
if (phoneFive == null)
Thread.Sleep(50);
phoneFive = new Phone
Manufacturer = "Apple",
Model = "xxxxx",
Owner = new Person
Age = 100,
Name = "伍华聪",
Profession = "计算机",
Surname = "wuhuacong"
phones.SetEntry(phoneFive.Id.ToString(), phoneFive);
client.Store&Phone&(
Manufacturer = "LG",
Model = "test-xxx",
Owner = new Person
Name = "test",
Profession = "teacher",
Surname = "wuhuacong"
var message = "Phone model is " + phoneFive.Manufacturer + ",";
message += "Phone Owner Name is: " + phoneFive.Owner.N
Console.WriteLine(message);
以上就是关于Redis的安装以及简单的例子使用说明,在具体中,我们可以利用Redis的高性能特性,来构建我们的缓存数据,并且可以利用Redis和MongoDB数据库的完美衔接,可以整合一起做的更好,为相关的后台提供更高效的数据处理操作,毕竟在互联网的大环境下,性能是非常重要的。
主要研究技术:代码生成工具、会员管理系统、客户关系管理软件、病人资料管理软件、Visio二次开发、酒店管理系统、仓库管理系统等共享软件开发。
专注于Winform开发框架/混合式开发框架、Socket开发框架、Web开发框架、Bootstrap开发框架、微信门户开发框架的研究及应用。使用 MongoDB 有没有必要用 Memcached 做缓存? - 知乎58被浏览10802分享邀请回答4添加评论分享收藏感谢收起2添加评论分享收藏感谢收起查看更多回答用户名:菜菜光
文章数:149
评论数:120
访问量:255475
注册日期:
阅读量:1297
阅读量:3317
阅读量:580592
阅读量:462658
51CTO推荐博文
这段时间对memcache,redis,mongodb 3种nosql进行了熟悉,简单的总结了下。1.从3者的性能来看,memcache性能是最好的,redis次之(redis有单进程限制,会碰到cpu 100%的限制,这个也比较难比较,一个多进程,一个单进程)2.从ha和scale out的角度来看,mongodb的灵活性和可用性最高。。memcache本身不怎么支持高可用。。需要前端实现persistencehash或者proxy。。Redis虽然支持m-s和m-s-s的结构,但是其对网络的依赖比较大,m-s之间的丢包也可能导致一次全量的镜像产生。Redis和memcache的横向扩展方式是一样的,但是单个的redis比较容易遇到cpu的瓶颈3.从存储的数据类型来看,mongodb最丰富,而且操作也比较灵活,支持类sql的查询。。memcache是纯粹的key-value,数据结构单一4.从数据的备份角度来看,memcache数据备份不太方便,需要3方工具,redis可以用持久化,mongodb的数据备份方法则比较多。总结来说;1.如果业务对数据的持久化没什么要求,数据结构比较单一,目的是做前端缓存的话,memcache会提供比较好的性能表现2.如果业务对数据的持久化有要求,需要备份,支持读写分离的话,用redis做缓存比较合适(也可以做一部分的后端存储)3.mongodb主要是用在大量数据的后端存储上,支持autosharding和自动故障转移,可用性比较高和hadoop群集类似目前我们对nosql的使用还不太完善,包括一些监控,比如redis的定时monitor监控。对性能的分析也基本没有。。比如redis和mongodb都是有slow log的,但是我们线上都没有开启更没有进行分析。。。这个可能是后续要做的事情。。下面是一个简单的对比表:对比参数memcacheredismongodb数据库类型纯粹的key-value数据库,数据结构单一结构化数据库对象数据库支持数据类型stringstring,list,sort,sorted,hash丰富的数据表达,索引,类似于关系型数据库可用性没有数据冗余机制,使用一致性hash增加可用性支持ms,mss结构,slave重连主节点会导致一次全量同步产生,影响性能和效率。可以实现读写分离,slave重连使用全量数据,性能和效率会有问题,不支持自动sharding,需要程序上实现一致性hash支持ms,支持replication set,set可以自动故障转换,支持autosharding持久化支持数据完全放在内存中,没有持久化支持支持持久化,快照持久化和aof持久化1.8版本开始采用binlog方式支持持久化的可靠性内存空间优化最大内存限制,LRU算法淘汰(可选)独立的vm机制,最大内存限制,数据ttl过期设置,内存淘汰(可选)依赖于操作系统的vm管理机制,使用内存映射文件,把剩余内存作为缓存使用,没有最大内存限制,数据存在文件系统上和内存是否是多线程是,可以通过-t控制进线程数单线程多线程性能15W/s的GET,11W/s的SET单个实例qps:8.5W左右(GET/SET)(RH2285)单个qps:3.5W左右(GET/SET)(RH2285)事务支持并发场景下,用cas保证一致性事务支持比较弱,保证每个事务操作连续执行,如果一个操作失败,不会回滚。使用乐观锁实现cas。不支持事务数据分析简单的get查询功能简单查询功能,支持对集合和hash的操作等查询方便,有类似于sql的语法,支持条件查询应用场景常作为前端缓存缓存和数据存储,队列大数据量存储feature支持使用pipeline减少查询次数auto sharding,故障自动切换,mapreduce支持,大文件下的GridFs文件系统安全性问题目前没有身份验证支持密码验证(requirepass)支持collection级别的身份验证(auth)数据备份和还原数据存放于内存中,不方便备份和还原(stats cachedump)可以使用持久化做备份和还原mongodump倍份,mogorestore还原。数据导出:mongoexport,mongoimport,导出数据支持csv格式slowlog相关没有slowlog相关的设置支持slowlog,slowlog存在于数据库中,使用slowlog get获取相关日志,slowlog的大小有限制,超过后会删除旧的支持slowlog(profiling),slowlog存在于system.profile(capped collection)的collection中状态查看statsinfomongostat,db.serverStatus(),db.stats(),rs.statsu()等当前操作查看monitormongosniff,db.currentOp()tunning1.object size不要太大(默认只支持1M)2.object 的expires设置(缓存应该具有超时的特点)3.适合数据处理后的缓存,不适合缓存后的处理输出1.开启vm,将不常用的value值给交换到磁盘上2.尽量将数据存放在内存中3.前端使用proxy或persistencehash来实现均衡访问4.使用master-slave结构,做读写分离5.大数据量时持久化数据dump时影响服务,应该放在slave端做6.使用pipeline聚合访问7.网卡bonding1.索引相关(读多写少时) 2.explain解析查询3.限定返回条目(limit)4.只查看指定需要字段,不查询所有字段5.使用capped collection (特殊业务)6.使用replsets,扩展整体集群能力本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)

我要回帖

更多关于 mysql数据库缓存 的文章

 

随机推荐