zoukankan      html  css  js  c++  java
  • 基于.net ,使用几种常见的NoSQL数据库

    shanzm-2020年1月10日 10:10:10
    本文只是我的一个Github仓库的自述文件,
    详细的各个NoSQL的驱动API可查看 [仓库](https://github.com/shanzm/NoSQL) 中的代码

    0 .net中的缓存对象

    • 因为需要向服务器多次请求相同的数据,为了减轻服务器压力,所以引入缓存。
    • 在.net中的缓存类为MemoryCache(.net 4.0引入),其继承于ObjectCache抽象类,并且实现了IEnumerableIDisposable接口。和ASP.NET中的HttpContext.Cache对象具有相同的功能!但是MemoryCache更加通用,也是可以使用在ASP.NET中的。
    • MemoryCache对象的数据形式为键值对形式
    • MemoryCache对象可以设置缓存的时间
    • MemoryCache是存入到程序进程的内存中的,程序重启之后就没了
    • 项目若是使用的是服务器集群,那么因为程序请求不同的服务器,缓存在各个服务器中不能共享,所以数据要在不同的服务器中缓存,所以需要占用大量的内存,此时使用程序内缓存就不合适了
      所以,如果数据量比较大或者集群服务器比较多,就要用单独的分布式缓存了,也就是搞一台或者多台专门服务器保存缓存数据,所有服务器都访问分布式缓存服务器。

    示例:(详见:001MemoryCache

    
    //添加引用:System.Runtime.Caching
    //新建一个缓存对象,使用默认的缓存对象
    MemoryCache memCache = MemoryCache.Default;
    //缓存以键值对的形式存储,缓存的生命期是10s
    memCache.Add("name", "shanzm", DateTimeOffset.Now.AddSeconds(10));
    


    1.MemCached

    • Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。

    • 使用Memcached的目的:通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。

    • MemCached存储的数据形式是键值对的形式,可以简单的理解为一个大Dictionary<key ,value>

    • MemCached存储的数据在服务器的内存中,读取效率较高,但是客户端和服务器之间的通讯是通过网络通讯,所以效率不及使用.net中的缓存对象缓存

    • 当然也是因为MemCached存储的数据写在内存中,所以服务器重启之后则数据全部即被清空。

    • 官网上并未提供 Memcached 的 Windows 平台安装包,需要自行编译。安装包下载:推荐一个编译好的安装包

    • 注意ADO.Net只支持关系型数据库,所以在.net中使用NoSQL数据库需要自行安装驱动。

    • 注意.net下的MemCached驱动有很多,推荐使用EnyimMemcached
      NuGet:PM> Install-Package EnyimMemcached

    • MemCached中的Cas操作:(详见:003Cas操作

    简单示例:(详见:002MemCachedDemo

    //创建配置对象
    MemcachedClientConfiguration memConfig = new MemcachedClientConfiguration();
    memConfig.AddServer("127.0.0.1:11211");
    //若是Memcached集群,此处可以同时添加多个服务器ip地址,然后客户端根据自己的算法决定把数据写入哪个 Memcached 实例
    
    //创建MemcachedClient对象
    using (MemcachedClient memClient = new MemcachedClient(memConfig))
    {
        //写入MemCached中
        memClient.Store(Enyim.Caching.Memcached.StoreMode.Set, "Name", "shanzm");
        memClient.Store(Enyim.Caching.Memcached.StoreMode.Set, "Age", "100");
    
        //读取数据
        string name = memClient.Get<string>("Name");
        if (name == null)
        {
            Console.WriteLine("无缓存");
        }
        else
        {
            Console.WriteLine(name);
        }
    
        //删除数据
        Console.WriteLine(memClient.Get<string>("Age"));
        memClient.Remove("Age");
        if (null == memClient.Get<string>("Age"))
        {
            Console.WriteLine("已经将Key为Age的数据从MemCached服务器中清除");
    
        }
        Console.ReadKey();
    }
    
    • 关于MemCached集群:
      • memcached 重启之后短时间内大量的请求会涌入数据库,给数据库造成压力,解决这个的方法就是使用集群,有多台 Memcached 服务器提供服务
      • Memcached 服务器的“雪崩”问题:如果所有缓存设置过期时间一样,那么每隔一段时间就会造成一次数据库访问的高峰。解决方法:缓存时间设置不一样,比如加上一个随机数。
      • Memcached 的集群实现很简单,集群节点直接不进行通讯、同步,只要在多个服务器上启动多个Memcached 服务器即可,客户端决定把数据写入不同的实例,不搞主从复制,每个数据库实例保存一部分内容


    2.Redis

    • Redis是完全开源免费的,是一个高性能的key-value数据库

    • 相对于MemCached等NoSQL数据库其有如下特点:

      • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
      • Redis 中value数据类型有6种,同字符串(String), 哈希(Hash), 列表(list), 集合(set) 和 有序集合(sorted set),经纬度(geo,仅限Redis3.2以上版本)
      • Redis支持数据的备份,即master-slave模式的数据备份。
    • Redis的所有操作都是原子性的( Atomicity),即和SQL中的事务一样:要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。

    • Redis与MemCached对比:

      • Redis是单线程的,因此单个Redis实例只能使用一个CPU核,无法发挥CPU的所有性能,亦是如此,所以一台服务器上可以运行多个Redis实例,不同实例监听不同的端口,再组成集群。对比于MemCached,MemCached是多线程的,可以充分的利用CPU多核的性能
      • MemCached保存的键值对的value只能是字符串类型,对象类型只能序列化为Json字符串
      • Redis会把数据写入磁盘,而Memcached只写入内存,重启即清空。
      • 简而言之:Memcached 只能当缓存服务器用,也是最合适的;Redis 不仅可以做缓存服务器(性能没有 Memcached 好),还可以存储业务数据。
    • 虽然Redis是默认有16个数据库,但是因为单线程的原因,不同的项目使用同一个Redis实例的不同库,效率不高,所以一般一个项目使用一个Redis实例,使用默认的db0库,即该实例的第一个库(索引为0)

    • 注意:Redis和MemCached一样,所有的键值对数据都是存放在一个库中(即数据不隔离),不同项目,不同程序,只要是使用的是同一个服务器,则他们的数据都存放在一个库中,所以存放数据的时候要注意key的命名方式,防止重复,造成对已存入的数据的覆盖。

    • 安装Redis(官方无windows版,微软自己维护一个开源版本

    • 常用的命令:参考

    • 安装Redis GUI客户端:RedisDesktopManager (推荐一个cracked 2019.5版本

    • Redis在.net下的驱动也多个,ServiceStack.Redis 和StackExchange.Redis(推荐)
      NuGet:PM>Install-Package StackExchange.Redist(注意其所支持的dotnet版本)
      官方地址

    • Redis中的六种数据类型的具体操作及使用案例

      005使用Redis计算新闻点击量
      006Redis中的list使用
      007模拟注册发送邮件验证
      008Redis中的set使用
      009Redis中的sorted set使用
      010Redis中使用sorted set实现热搜
      011Redis中使用hash使用
      012Redis中的geo使用(注意只支持最新版本的Redis)
      015Redis实现随机分红包

    简单示例:(详见:004RedisDemo)

    //注意此处我们使用异步方法
    using (ConnectionMultiplexer conn = await ConnectionMultiplexer.ConnectAsync("127.0.0.1:6379"))
    {
        //默认是0号数据库,若是其他数据库,如3号数据库,conn.GetDatabase(3)
        IDatabase db = conn.GetDatabase();
    
        //写入数据
        await db.StringSetAsync("Name", "张三", TimeSpan.FromSeconds(10));
    
        //批量写入(使用Redis中Batch对象 见013Redis的批量操作)
        KeyValuePair<RedisKey, RedisValue>[] kvs = new KeyValuePair<RedisKey, RedisValue>[3];
    
        kvs[0] = new KeyValuePair<RedisKey, RedisValue>("A", "a");
        kvs[1] = new KeyValuePair<RedisKey, RedisValue>("B", "b");
        kvs[2] = new KeyValuePair<RedisKey, RedisValue>("C", "c");
        await db.StringSetAsync(kvs);
    
        //读取数据(查询不到数据返回为null)
        string name = await db.StringGetAsync("Name");
        string A = await db.StringGetAsync("A");
    
        //删除数据
        db.KeyDelete("A");
    
        //判断是否存在某条数据
        if (!db.KeyExists("A"))
        {
            MessageBox.Show("已删除Key值为‘A’的数据");
        }
    
        //对已经存储的数据设置过期时间
        db.KeyExpire("B", TimeSpan.FromSeconds(10));
    }
    


    3.MongoDB

    • MongoDB 是一个面向文档存储的数据库,即文档型数据库。存储方式也是key-value,其中value只能是“文档”,在MongoDB中的文档类似于Json对象。(其中的数据以"filed :value"书写)

    • 因为数据是和Json类似的字符串(其实我感觉就是Json字符串),所以不需要预先定义表结构,同一个“表”中可以保存多个格式的数据。

    • Mongodb 没有“数据一致性检查”、“事务”等,不适合存储对数据事务要求高(比如金融)的数据;只适合放非关键性数据(比如日志或者缓存)。

    • 注意MongoDB中我们所说的表即其中的Collection

    • 安装MongoDB(官方地址

    • 安装MongoDB GUI客户端:Robo3T

    • 注意.net中的MongoDB的驱动,有微软官方开发:
      NuGet:PM>Install-Package MongoDB.Driver -Version 2.5.0
      (注意默认安装最新版本可能会报错
      亲测2.5.0版本和 .net Framework版本是4.6.1完美支持)

    • MongoDB中的完整的增删改查,见:017MongoDB中的CURD

    简单示例:(详见:016MongoDBDemo

    //连接MongoDB服务,创建对象
    MongoClient client = new MongoClient("mongodb://127.0.0.1:27017");
    //获取名为:TestDb1的数据库,若是没有则创建!
    IMongoDatabase db = client.GetDatabase("TestDb1");
    //获取名为名为Personsde表(collection可以理解为表)若是没有则创建!
    IMongoCollection<Person> persons = db.GetCollection<Person>("Persons");
    
    
    Person p1 = new Person() { Id = 0001, Name = "shanzm", Age = 25 };
    Person p2 = new Person() { Id = 002, Name = "shanzm" };//MongoDB会对Age默认填充为0
    
    persons.InsertOne(p1);
    persons.InsertOne(p2);
    
    
  • 相关阅读:
    Java编程之路相关书籍
    JAVA中的Random()函数
    在鼠标右键上加入使用notepad++编辑
    更改IE浏览器的收藏夹位置
    Java四类八种数据类型
    成为Java顶尖程序员 ,看这11本书就够了
    面向对象(多异常的声明与处理)
    面向对象(异常try-catch)
    面向对象(异常概述)
    面向对象(局部内部类和匿名内部类)
  • 原文地址:https://www.cnblogs.com/shanzhiming/p/12175031.html
Copyright © 2011-2022 走看看