65.9K
CodeProject 正在变化。 阅读更多。
Home

Angular MVC API 应用程序中的 Windows Cassandra

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (3投票s)

2016年2月24日

CPOL

7分钟阅读

viewsIcon

17600

关于一个基于 ASP.NET Web API 2 和 Cassandra NoSQL 数据库的单页 Angular 站点的思考

引言

在长期从事微软技术栈开发并处理关系型数据库之后,我也到了该看看 NoSQL 数据库光明一面的时候了。选择 Cassandra 是一个偶然。我从未研究过 NoSQL 数据库,也没有比较过它们的性能或特性。它只是碰巧第一个出现在我面前。于是我开始玩转它,经过一段时间的自学和研究,我决定分享我将其与微软技术结合使用的经验。我知道 Cassandra 是 Priam、Hecuba、Apache 和 Facebook 的后代,并且预定运行在 Unix/Linux/Ubuntu 等系统上,但我想要它在 Windows 上运行...

我希望我这些不才的练习 能对那些想将 Cassandra 与微软技术结合使用的人有所帮助。

背景

在继续阅读之前,您需要了解什么是 Cassandra、Angular 和 ASP.NET Web API。如果您还不了解,请查阅 DataStaxCassandraASP.NET Web API 2Angular。DataStax 分发了 Windows 版 Cassandra,并提供了自己的查询和数据构建工具。

Using the Code

好的,现在在学习了所有安装和理解了集群、键空间、列族、聚合键是什么,以及什么是抗熵(Anti-Entropy)和读修复(Read Repair)、内存表(memtables)和布隆过滤器(bloom-filters)之后,我们需要了解数据绑定(databinding)、控制器(controllers)、作用域(scopes)、服务(services)、依赖注入(dependency injection)、过滤器(filters)、模块(modules)和指令(directives)是什么。啊,当然还要熟悉 .NET、C# 和 ASP.NET MVC。但即使我们遗漏了什么,也没关系,我们会尝试学习它。

我们开始吧!

安装 DataStax DevCenter 1.5 后,您将在应用程序列表中看到新添加的应用程序。这是我在 Windows 8 上看到的景象。

运行 DataStax DevCenter 应用程序。对我来说,它具有 Eclipse 的外观和感觉。

首先,我们需要在 DevCenter 左上角的 Connections 窗格中创建一个新连接。右键单击它并选择 **Open Connection**。在打开的窗口中,在 Connection name 输入框中输入连接名称,在 contact hosts 中输入 127.0.0.1。将来,我们会添加多个主机,但现在一个主机就足够了。单击 Contact hosts 输入区域右侧的 add。Native protocol port 是 9042。保存表单。

如果一切正常,您将连接到 Cassandra 数据库,并在 Connections 窗格中看到一个新添加的连接。

现在,一切就绪,让我们深入到创建键空间(keyspaces)和列族(column families)的迷人世界。您可以将键空间视为一个数据库。键空间是 Cassandra 中最外层的数据容器。听起来就像 SQL Server、Oracle 或 MySql 世界中的数据库。就像数据库是表的容器一样,键空间是列族的容器。因此,您可以将它们视为表。

DataStax 安装时,会在您的 PC 上的 Program Files 中创建一个 DataStax 文件夹。在那里,找到 DevCenter,然后是 examples,您会发现六个 CQL 文件。

CQL 是上下文查询语言(Contextual Query Language)的缩写。它看起来像 SQL,但并非完全相同。这种差异源于这两种数据库存储和检索数据的不同概念。一种是关系型数据库,另一种是键值存储。所以忘记 JOIN、GROUP BY 和 FOREIGN KEY。

其中一个文件名为 videodb-schema。我们来打开它。第一行写着:

CREATE KEYSPACE videodb WITH REPLICATION = 
   { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };

此命令将创建键空间 videodb,正如我们可以猜到的那样。'Class' 是副本放置策略(replica placement strategy)的名称。对于仅用于单个数据中心的,可以是 SimpleStrategy 。如果您需要多个数据中心,请选择 NetworkTopologyStrategy。我们这里不需要。所以我们的类是 SimpleStrategy

复制因子(Replication factor)是一个参数,它决定了您的集群中有多少个节点存储数据的副本。例如,如果复制因子设置为 2,那么每个数据的两个副本将存储在不同的节点上。常识告诉我们,复制因子不能大于集群中的节点数。您不能在只有 8 个可用节点的情况下存储 10 个数据副本。如果您尝试这样做,您的写入将失败。我们有一个节点,复制因子将是 1。

在 DataStax DevCenter 的中间大面板中运行此命令后,我们将在右上角的 schema 窗格中看到一个新键空间已添加到已有的默认键空间中。

 

现在我们可以选择我们的新键空间并对其进行操作。

不要忘记选择您的连接。

好的,现在我们准备创建表了。哦,抱歉,在我们的新 NoSQL 世界中是列族。

转到我们的 videodb-schema 文件,将所有 CREATE TABLE 命令复制到 DevCenter 的中间面板,然后运行“execute cql script”按钮(绿色背景上的白色三角形)。

现在我们将展开 videodb schema。

在 schema 窗格中可以看到所有称为“表”的列族。

不,现在我们有了数据库 schema,让我们添加一些数据。

打开 videodb-inserts 文件,复制其内容并运行 execute 按钮。

要检查一切是否正确,请询问 Cassandra。

select * from videos;

结果应该如下所示

为了处理 Cassandra,我们还有一个更轻量级的工具——Cassandra CQL Shell。对于我上面写的所有这些任务,您都可以使用这个工具。只需打开它。

Run

use videodb;

然后您就连接到了 Cassandra。现在它已准备就绪,可以响应您的命令。让我们问它一些问题。

select * from users;

结果应该如下所示。

现在我们有了包含数据的数据库。是时候编码了!

在这一部分,我们将创建一个简单的控制台应用程序,该应用程序将连接到 Cassandra 并执行一些基本查询,之后,我们将继续进行所宣布的 Angular 和 MVC API。

打开您的 Visual Studio 并创建一个控制台应用程序项目。转到 NuGet Package Manager 并搜索 DataStax 的 CassandraCSharpDriver

安装它,并确保 Cassandra 引用已添加到您的项目中。

创建 CassandraEngine 类并添加以下内容:

 public class CassandraEngine
    {
        private Cluster cluster;
        private ISession session;

        public CassandraEngine()
        {
            SetCluster();
        }

        private void SetCluster()
        {
            if (cluster == null)
            {
                cluster = Connect();
            }
        }

        public ISession GetSession()
        {
            if (cluster == null)
            {
                SetCluster();
                session = cluster.Connect();
            }
            else if (session == null)
            {
                session = cluster.Connect();
            }

            return session;
        }

        private Cluster Connect()
        {
            //string user = GetAppSetting("cassandraUser");
            //string pwd = GetAppSetting("cassandraPassword");
            string[] nodes = GetAppSetting("cassandraNodes").Split(',');

            QueryOptions queryOptions = new QueryOptions()
               .SetConsistencyLevel(ConsistencyLevel.One);

            Cluster cluster = Cluster.Builder()
                .AddContactPoints(nodes)
                .WithDefaultKeyspace("videodb")
                // .WithCredentials(user, pwd)
                .WithQueryOptions(queryOptions)
                .Build();

            return cluster;
        }

        private string GetAppSetting(string key)
        {
            return ConfigurationManager.AppSettings[key];
        }

        private void Close()
        {
            cluster.Shutdown();
        }
    }

您可以看到我注释掉了一些行以供将来使用。之后,我们将看到如何使用用户名和密码连接到 Cassandra,并在另一台计算机上创建额外的节点,然后尝试使用具有两个节点的 Cassandra。我不认为有理由在单台机器上运行 Cassandra。但这符合我们的培训目的。

我们的 config 文件非常简单,现在只有一个键。

  <appSettings>
    <add key="cassandraNodes" value="127.0.0.1"/>
  </appSettings>

Connect 方法中,我们从配置文件中获取节点的 IP。

string[] nodes = GetAppSetting("cassandraNodes").Split(',');

在接下来的部分中,如我所提到的,我们将添加更多节点,并且节点的数组将有意义。到目前为止,我们只有一个在 localhost 上运行的节点。还记得我们上面在 DataStax DevCenter 中创建的那个吗?

之后,我们正在设置一致性级别(Consistency Level)。嗯,一致性级别是指我们希望如何将行同步到所有 Cassandra 节点。它可以是十几种选项之一。一致性级别数字决定了在 Cassandra 向客户端应用程序返回 OK 之前,写入必须成功多少个副本。在我们的例子中,它设置为一。正如您可以理解的,在至少一个节点的提交日志(commit log)和 memtable 写入后,该过程将被视为成功。

下一个命令使用节点 IP、凭据(如果我们有)、默认键空间和上述一致性级别构建集群。

现在,转到我们的 Program 类。

    class Program
    {
        protected static ISession session;
        protected static IMapper mapper;

        static void Main(string[] args)
        {
            CassandraEngine engine = new CassandraEngine();
            session = engine.GetSession();
            GetUsers();
            Console.ReadLine();
        }

        public static void GetUsers()
        {
            string json = string.Empty;
            var rows = session.Execute("SELECT * FROM videodb.users;");

            foreach (var row in rows)
            {
                Console.WriteLine("\n");
                Console.WriteLine(row.GetValue(row.GetColumn("username").Type, 0) == null ? 
                "" : row.GetValue(row.GetColumn("username").Type, 0).ToString());
                Console.WriteLine(row.GetValue(row.GetColumn("created_date").Type, 1) 
                == null ? "" : row.GetValue(row.GetColumn("created_date").Type, 1).ToString());
                Console.WriteLine(row.GetValue(row.GetColumn("email").Type, 2) == null ? 
                new List<string>() : row.GetValue(row.GetColumn("email").Type, 2) 
                as List<string>);
                Console.WriteLine(row.GetValue(row.GetColumn("firstname").Type, 3) == null ? 
                "" : row.GetValue(row.GetColumn("firstname").Type, 3).ToString());
                Console.WriteLine(row.GetValue(row.GetColumn("lastname").Type, 4) == null ? 
                "" : row.GetValue(row.GetColumn("lastname").Type, 4).ToString());
                Console.WriteLine(row.GetValue(row.GetColumn("password").Type, 5) == null ? 
                "" : row.GetValue(row.GetColumn("password").Type, 5).ToString());
                Console.WriteLine("===========================================");
            }                
        }
}

在这里,我们正在初始化我们的 CassandraEngine,获取会话并选择用户。

您可以看到我没有指示查询使用哪个键空间,因为它是在构建集群时设置的。但通常,您可以使用 select 命令,如下所示。

use videodb; SELECT * FROM videodb.users;

我们不限于一个应用程序只能使用一个键空间。在我们的例子中,我使用的是一个键空间,但可能不止一个。

有趣的是,当您使用...

SELECT * FROM

...返回的列不是按照您在 CREATE TABLE 命令中声明的顺序,而是按字母顺序排列,主键列除外,它首先出现,索引为零。

我正在使用方法...

public object GetValue(Type type, int index)

...它接受类型和列索引。所以,如果我想获取用户的名字,我需要知道列类型和列索引。名字的索引是 3,在 usernamecreated_dateemail 之后。

另一点是 CQL 数据类型以及如何将其转换为 .NET 类型。如果您还记得 schema 列表,我们的 users 列族具有 varchar 类型的 email 列表。Cassandra 的列表转换为 .NET 时,会变成一个有序元素的集合,所以代码中使用的字符串列表对于 email 来说应该没问题。

就是这样!让我们运行我们的应用程序,看看输出。

很简单,不是吗?

下次,我们将创建用户定义函数(user defined functions)、用户定义类型(user defined types)和元组(tuples)。我们将尝试将 Cassandra 的数据作为 .NET 对象接收,插入 JSON 数据,并开始处理我们的 API。

感谢阅读!

历史

  • 2016 年 2 月 24 日:初始版本
© . All rights reserved.