ServiceStack.Redis实践
   Redis的C#客户端我选择的是ServiceStack.Redis,相比Booksleeve redis-sharp等方案,它提供了一整套从 Redis数据结构都强类型对象转换的机制;看一个例子来了解一下ServiceStack.Redis是如何组织数据的,我们使用的实体类定义如下:

?

1
2
3
4
5
6
7
8
9
10
11 public class User
   {
       public User()
       {
           this.BlogIds = new List<long>();
       }
 
       public long Id { get; set; }
       public string Name { get; set; }
       public List<long> BlogIds { get; set; }
   }</long></long>
使用下面的代码片段,我们存入两条数据到Redis:

?

1
2
3
4
5
6
7 using (var redisUsers = redisClient.GetTypedClient<user>())
        {
            var ayende = new User { Id = redisUsers.GetNextSequence(), Name = "Oren Eini" };
            var mythz = new User { Id = redisUsers.GetNextSequence(), Name = "Demis Bellot" };
            redisUsers.Store(ayende);
            redisUsers.Store(mythz);
          }</user>
我们看下Redis中的结果:

?

1
2
3
4
5 redis 127.0.0.1:6379[1]> keys *
1) "seq:User"
2) "ids:User"
3) "urn:user:1"
4) "urn:user:2"
我们逐一检查一下数据类型:
 seq:User    
string  
维护当前类型User的ID自增序列,用做对象唯一ID
 ids:User
set       
同一类型User所有对象ID的列表
 urn:user:1
string 
user对象
seq:User 维护的是类型User的ID序列 redisUsers.GetNextSequence()

?

1
2
3
4
5
6
7
8 public long GetNextSequence(int incrBy)
  {
             return IncrementValueBy(SequenceKey, incrBy);
  }
 public long IncrementValue(string key)
    {
              return client.Incr(key);
     }
这里的SequenceKey就是 "seq:User",然后我们通过存一个对象到Redis看另外两个key是什么作用:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public T Store(T entity)
       {
           var urnKey = entity.CreateUrn();
           this.SetEntry(urnKey, entity);
 
           return entity;
       }
       //entity.CreateUrn();的结果是"urn:user:1"
       public void SetEntry(string key, T value)
       {
           if (key == null)
               throw new ArgumentNullException("key");
 
           client.Set(key, SerializeValue(value));
           client.RegisterTypeId(value);
       }
 
       internal void RegisterTypeId<t>(T value)
       {
           var typeIdsSetKey = GetTypeIdsSetKey<t>();
           var id = value.GetId().ToString();
 
           if (this.Pipeline != null)
           {
               var registeredTypeIdsWithinPipeline = GetRegisteredTypeIdsWithinPipeline(typeIdsSetKey);
               registeredTypeIdsWithinPipeline.Add(id);
           }
           else
           {
               this.AddItemToSet(typeIdsSetKey, id);
           }
       }</t></t>  
这里的typedIdsSetKey 就是"ids:User"

ids:User相当于一个索引,包含了所有同为类型User的ID;由于维护了这样一个分组信息,所以很容易实现GetAll()这样的功能;
在redis-cli中查询一下 get urn:user:1 返回值是 JSON格式:
"{\"Id\":1,\"Name\":\"Oren Eini\",\"BlogIds\":[1]}"
 
ServiceStack.Redis 自己实现了一套序列化功能, Fastest JSON Serializer for .NET released 支持 POCO(Plain Old CLR Object)序列化.
 
   实际应用中,由于我们使用的数据是来自关系型数据库,本身包含关联关系,所以并不需要这样的对象组织方式;我们只需要把关系型数据中一对多的关系在Redis中表达出来即可;这里我扩展修改了RedisClient的实现,由于RedisClient本身已经通过 partial方式 分割成若干个文件,所以很容易把变动的代码集中在同一个代码文件中.具体业务对象存储,主帖和回帖会有字段级修改,所以设计成为Hash结构,其它几个子对象读写都是以对象为单位,设计成为POCO方式持久化;
使用管道Pipeline遇到的问题
  使用管道可以将客户端到Redis的往返次数减少,不过在使用ServiceStack.Redis的时候,遇到这样一个问题,比如要把一个List全部存储,代码不可以写成下面这样:

?

1
2
3
4
5
6
7
8
9 %%第一种写法
           logs.ForEach(n =>
                {
                    pipeline.QueueCommand(r =>
                    {
                        ((RedisClient)r).Store<oplog>(n, n.GetObjectID(), n.GetUrnKey());
                        ((RedisClient)r).Expire(n.GetUrnKey(), dataLifeTime);
                    });
                });</oplog>
而是要写成这样:

?

1
2
3
4
5
6
7
8 %%第二种写法
 logs.ForEach(n =>
                {
   
                    pipeline.QueueCommand(r => ((RedisClient)r).Store<log>(n, n.ID, n.GetUrnKey()));
                    pipeline.QueueCommand(r => ((RedisClient)r).Expire(n.GetUrnKey(), dataLifeTime));
 
                });</log>
什么原因呢?RedisQueueCompletableOperation的AddCurrentQueuedOperation方法会在
执行CurrentQueuedOperation =
null;如果按照第一种写法会丢失回调函数,这就造成有返回值在没有及时提取,后续的操作获取返回值时首先取到的是积压的结果信息,就出现了异常,而第
二种写法就避免了这个问题.
1
2
3
4
5
protected virtual void AddCurrentQueuedOperation()
      {
          this.QueuedCommands.Add(CurrentQueuedOperation);
          CurrentQueuedOperation = null;
      }

Redis基础(转)的更多相关文章

  1. windows下使用redis,Redis入门使用,Redis基础命令

    windows下使用redis,Redis入门使用,Redis基础命令 >>>>>>>>>>>>>>>> ...

  2. [.net 面向对象程序设计深入](14)Redis——基础

    [.net 面向对象程序设计深入](14)Redis——基础 很长一段时间没更新博客了,坚持做一件事,真不是件容易的事,后面我会继续尽可能的花时间更新完这个系列文章. 因这个系列的文章涉及的范围太大了 ...

  3. linux redis基础应用 主从服务器配置

    Redis基础应用 redis是一个开源的可基于内存可持久化的日志型,key-value数据库redis的存储分为内存存储,磁盘存储和log文件三部分配置文件中有三个参数对其进行配置 优势:和memc ...

  4. [.net 面向对象程序设计深入](36)Redis——基础

    [.net 面向对象程序设计深入](36)Redis——基础 很长一段时间没更新博客了,坚持做一件事,真不是件容易的事,后面我会继续尽可能的花时间更新完这个系列文章. 因这个系列的文章涉及的范围太大了 ...

  5. mysql主从复制、redis基础、持久化和主从复制

    一.mysql(mariadb)基础 1.基础命令(centos7操作系统下) 1.启动mysql systemctl start mariadb 2.linux客户端连接自己 mysql -uroo ...

  6. Redis基础用法、高级特性与性能调优以及缓存穿透等分析

     一.Redis介绍 Redis是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库.缓存服务或消息服务使用.Redis支持多种数据结构,包括字符串.哈希表.链表.集合.有序集合.位图.Hype ...

  7. Redis基础知识补充及持久化、备份介绍(二)--技术流ken

    Redis知识补充 在上一篇博客<Redis基础认识及常用命令使用(一)--技术流ken>中已经介绍了redis的一些基础知识,以及常用命令的使用,本篇博客将补充一些基础知识以及redis ...

  8. Spring-Boot之Redis基础

    Spring-Boot之Redis基础 准备 Redis下载地址:github.com/MSOpenTech/redis/releases Redis数据库的默认端口号是 6379 开启Redis服务 ...

  9. mongodb,Mysql,redis基础教程

    数据库基础 1:mongodb基础教程 1:pymongo基础教程  2:Mysql基础教程 3:redis基础教程

  10. Redis基础知识点面试手册

    Redis基础知识点面试手册 基础 概述 数据类型 STRING LIST SET HASH ZSET(SORTEDSET) 数据结构 字典 跳跃表 使用场景 会话缓存 缓存 计数器 查找表 消息队列 ...

随机推荐

  1. iOS开发 - OC - 实现本地数据存储的几种方式二(直接使用sqlite)

    连接上一篇文章http://www.cnblogs.com/FBiOSBlog/p/5819418.html. 上一篇文章介绍了OC内部一些方法进行数据的本地存储,其中包括 NSUser类.Plist ...

  2. python——argsort函数

    numpy中argsort函数用法,有需要的朋友可以参考下. 在Python中使用help帮助 >>> import numpy >>> help(numpy.ar ...

  3. 【HOW】用PowerShell脚本修改用户配置文件属性显示次序

    首先将如下脚本保存为PowerShell文件,如:ReorderUserProfileProperty.ps1. 在执行此脚本时,如果不输入任何参数,将列出所有用户配置文件属性的名称和显示次序:如果只 ...

  4. ssh那些事儿

    第一次使用ssh是上学期搭建hadoop集群的时候,当时照着各种配置文档费了九牛二虎之力终于把环境搭建成功,现在想想当时还真是不容易呢.好了废话不扯了,进入正题. 计算机发展早期能实现两台机器之间的通 ...

  5. 数据库使用--MySQL: InnoDB 还是 MyISAM?

    MyISAM存储引擎 MyISAM是 默认存储引擎.它基于更老的ISAM代码,但有很多有用的扩展.MyISAM存储引擎的一些特征: ·      所有数据值先存储低字节.这使得数据机和操作系统分离.二 ...

  6. Linux 性能监控之命令行工具

    引言 对于系统和网络管理员来说每天监控和调试Linux系统的性能问题是一项繁重的工作.这些命令行工具可以在各种Linux系统下使用,可以用于监控和查找产生性能问题的原因.这个命令行工具列表提供了足够的 ...

  7. 关于reset.css的疑问:为什么一定要重置浏览器样式?

    自开始做前端算起,我所做过的每一个项目中都会有一个reset.css,也就是重置样式表.我现在想想都不知道第一次是从哪儿弄来的一个重置样式表.快五年了,好像从来都没有质疑过关于重置样式表的内容. 这样 ...

  8. arcgis_engine_develop_error_42

    解决: 今天在VS2013打开程序时,手工添加了pageLayoutControl隔一会弹出错误窗口:Provide your license server administrator with th ...

  9. leetcode 189

    189. Rotate Array Rotate an array of n elements to the right by k steps. For example, with n = 7 and ...

  10. ASP.NET MVC4框架揭秘 源代码下载

    http://files.cnblogs.com/artech/asp.net.mvc.4.samples.rar