1、Redis 简介

Redis 是一个支持数据结构更多的键值对数据库。它的值不仅可以是字符串等基本数据

类型,也可以是类对象,更可以是 Set、List、计数器等高级的数据结构。
Memcached 也可以保存类似于 Set、List 这样的结构,但是如果说要向 List 中增加元素,
Memcached 则需要把 List 全部元素取出来,然后再把元素增加进去,然后再保存回去,不
仅效率低,而且有并发访问问题。

Redis 内置的 Set、List 等可以直接支持增加、删除元素的操作,效率很高,操作是原子的。

Memcached 数据存在内存中,memcached 重启后数据就消失;而 Redis 会把数据持久

化到硬盘中,Redis 重启后数据还存在。
2、Redis 的安装
redis for windows >=2.8 的版本支持直接安装为 windows 服务
https://github.com/MicrosoftArchive/redis
如果下载 msi 自动装完服务,如果下载 zip 需要按照下面的方法安装为服务:
https://raw.githubusercontent.com/MSOpenTech/redis/3.0/Windows%20Service%20Documenta
tion.md

3、redis 的优点:

  1. 1)  支持 string、list、set、geo 等复杂的数据结构。

  2. 2)  高命中的数据运行时是在内存中,数据最终还是可以保存到磁盘中,这样服务器重启之后数据还在。

  3. 3)  服务器是单线程的,来自所有客户端的所有命令都是串行执行的,因此不用担心并发修改(串行操作当然还是有并发问题)的问题,编程模型简单;

  4. 4)  支持消息订阅/通知机制,可以用作消息队列;

  5. 5)  Key、Value 最大长度允许 512M;

4、redis 的缺点:

  1. 1)  Redis 是单线程的,因此单个 Redis 实例只能使用一个 CPU 核,不能充分发挥服务器的性能。可以在一台服务器上运行多个 Redis 实例,不同实例监听不同端口,再互相组成集群。

  2. 2)  做缓存性能不如 Memcached;

5、Memcached 的优点:
       1) 多线程,可以充分利用 CPU 多核的性能;

2) 做缓存性能最高;

6、Memcached 的缺点:

  1. 1)  只能保存键值对数据,键值对只能是字符串,如果有对象数据只能自己序列化成 json字符串;

  2. 2)  数据保存在内存中,重启后会丢失;

  3. 3)  Key 最大长度 255 个字符,Value 最长 1M。

7、总结
      Memcached 只能当缓存服务器用,也是最合适的;Redis 不仅可以做缓存服务器(性能没有 Memcached 好),还可以存储业务数据。

8、redis 命令行管理客户端:

1)直接启动 redis 安装目录下的 redis-cli 即可。不用管恶心的自动提示。
执行 set name yzk,就是设置键值对 name=yzk 执行 get name 就是查找名字是 name 的值;  keys *是查找所有的 key  key *n*是查找所有名字中含有 n 的 key

2) 和 Redis 一样,Redis 也是不同系统放到 Redis 中的数据都是不隔离的,因此设定 Key 的
时候也要选择好 Key。
       3) Redis 服务器默认建了 16 个数据库,Redis 的想法是让大家把不同系统的数据放到不同
的数据库中。但是建议大家不要这样用,因为 Redis 是单线程的,不同业务都放到同一个 Redis
实例的话效率就不高,建议放到不同的实例中。

因此尽量只用默认的 db0数据库命令行下可以用 select0、select1 这样的指令切换数据库,最高为15。试试在不同数据
库下新建、查询数据。

4) 了解的常用的几个命令就可以。所有对数据的操作都可以通过命令行进行,后面讲
的.net 操作 Redis 的驱动其实就是对这些命令的封装。

9、redis GUI 管理客户端

GUI 客户端非常多,个人推荐使用 RedisDesktopManager安装后点击【Connect to Redis Server】连接服务器。展开节点可以看到所有的 Key,双击 Key 可以查看 Key 的值。在根节点上点右键,选择
【Console】,这样就可以输入命令。

10、.net 操作 Redis

用 StackExchange.Redis ,而不是 ServiceStack.Redis,因为 StackExchange.Redis 依赖组件 少,而且操作更接近原生的 redis 操作,ServiceStack 封装的太厉害,而且有过收费的“前科”。

Install-Package StackExchange.Redis
using (ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379"))
{

IDatabase db = redis.GetDatabase();//默认是访问 db0 数据库,可以通过方法参数指定数
字访问不同的数据库

db.StringSet("Name", "abc");

}

支持设置过期时间:db.StringSet("name", "rupeng.com", TimeSpan.FromSeconds(10))
获取数据:string s = db.StringGet("Name")如果查不到则返回 null

Redis 里所有方法几乎都支持异步,比如 StringGetAsync()、StringSetAsync(),尽量用异步方法。

注意看到访问的参数、返回值是 RedisKey、RedisValue 类型,进行了运算符重载,可以和 string、
byte[]之间进行隐式转换。

11、Key 操作
       Key 操作:因为 Redis 里所有数据类型都是用 KeyValue 保存,因此 Key 操作针对所有数据类型,
KeyDelete(RedisKey key):根据 Key 删除;KeyExists(RedisKey key)

判断 Key 是否存在,尽量不要用,
因为会有并发问题;KeyExpire(RedisKey key, TimeSpan?  expiry)、KeyExpire(RedisKey key, DateTime?
expiry)设置过期时间;
12、数据类型

Redis 支持的数据结构:string、list、set、sortedset、hash、geo(redis 3.2 以上版本)。对应
的 Redis 客户端里的方法都是 StringXXX、HashXXX、GeoXXX 等方法。

不同数据类型的操作方
法不能混用,比如不能用 ListXXX 写入的值用 StringXXX 去读取或者写 入等操作。
13、String 类型

可以用 StringGet、StringSet 来读写键值对,是基础操作StringAppend(RedisKey key, RedisValue value):向 Key 的 Value 中附加内容,不存在则新建;
可以用作计数器:db.StringIncrement("count", 2.5);

给 count 这个计数器增加一个值,如果不存在则从 0 开始加;db.StringDecrement("count",1)计数器减值;获取还是用 StringGet()获取字符串类型的
值。比如可以用这个来计算新闻点击量、点赞量,效率非常高。     

private static string XinWen_Prefix = "WWW_XinWen_";

public async Task<ActionResult> Index(int id)

{
using (ConnectionMultiplexer redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379")) { IDatabase db = redis.GetDatabase();//默认是访问 db0 数据库,可以通过方法参数指定数字访 问不同的数据库 //以 ip 地址和文章 id 为 key
string hasClickKey = XinWen_Prefix + Request.UserHostAddress + "_" + id; //如果之前这个 ip 给这个文章贡献过点击量,则不重复计算点击量 if(await db.KeyExistsAsync(hasClickKey)==false)
{ await db.StringIncrementAsync(XinWen_Prefix + "XWClickCount" + id, 1); //记录一下这个 ip 给这个文章贡献过点击量,有效期一天 db.StringSet(hasClickKey, "a", TimeSpan.FromDays(1)); } RedisValue clickCount = await db.StringGetAsync(XinWen_Prefix + "XWClickCount" + id); XinWenModel model = new XinWenModel();
model.ClickCount = Convert.ToInt32(clickCount);
return View(model); } return View(); }

14、list 类型

Redis 中用 List 保存字符串集合。 比如可以把聊天记录保存到 List 中;商品的物流信息记录。也  可以当成双向队列或者双向栈用,list 长度是无限。

ListLeftPush(RedisKey key, RedisValue value)从左侧压栈;RedisValue ListLeftPop(RedisKey key) 从左侧弹出;

ListRightPush(RedisKey key, RedisValue value ) 从右侧压栈;RedisValue ListRightPop(RedisKey key) 从右侧弹出;

RedisValue ListGetByIndex(RedisKey key, long index)获取 Key 为 key 的 List 中第 index 个元素的值; long ListLength(RedisKey key) 获取 Key 为 key 的 List 中元素个数;尽量不要用 ListGetByIndex、 ListLength 因为会有并发问题;。

如果是读取而不 Pop,则使用 ListRange:RedisValue[] ListRange(RedisKey key, long start = 0, long stop = -1)。不传 start、end 表示获取所有数据。指定之后则获取某个范围。

可以把 Redis 的 list 当成消息队列使用,比如向注册用户发送欢迎邮件的工作,可以在注册的流 程中把要发送邮件的邮箱放到 list 中,另一个程序从 list 中 pop 获取邮件来发送。

生产者、消费者模式。把生产过程和消费过程隔离。

15、set 类型
      如大家所知,set 是一种元素不重复的集合。
SetAdd(RedisKey key, RedisValue value)向 set 中增加元素

bool SetContains(RedisKey key, RedisValue value) 判断 set 中是否存在某个元素;
long SetLength(RedisKey key) 获得 set 中元素的个数;

SetRemove(RedisKey key, RedisValue value)从 set 中删除元素;

RedisValue[] SetMembers(RedisKey key)获取集合中的元素;

如果使用 set 保存封禁用 id 等,就不用做重复性判断了。

注意 set 不是按照插入顺序遍历的,而是按照自己的一个存储方式来遍历,因为没有保存插入的 顺序。

16、sortedset
     如果对于数据遍历顺序有要求,可以使用 sortedset,他会按照打分来进行遍历。
SortedSetAdd(RedisKey key, RedisValue member, double score) 在 key 这个 sortedset 中增加member,并且给这个 member 打分,如果 member 已经存在,则覆盖之前的打分;       doubleSortedSetIncrement(RedisKeykey,RedisValuemember,doublevalue) 给key中member这一项增加 value 分;

double SortedSetDecrement(RedisKey key, RedisValue member, double value):给 key 中 member 这一项减 value 分;

SortedSetEntry[] SortedSetRangeByRankWithScores(RedisKey key, long start = 0, long stop = -1,Orderorder=Order.Ascending) 根据排序返回sortedset中的元素以及元素的打分,start、stop用来分页
查询、order 用来指定排序规则。

测试:

db.SortedSetIncrement("Hotwords", "test", 1);

db.SortedSetIncrement("Hotwords", "test", 1); db.SortedSetIncrement("Hotwords", "test", 1); db.SortedSetIncrement("Hotwords", "杨中科", 1); db.SortedSetIncrement("Hotwords", "侯宝林", 1); db.SortedSetIncrement("Hotwords", "侯宝林", 1);
SortedSetEntry[] items = db.SortedSetRangeByRankWithScores("Hotwords"); foreach(var item in items) {
Console.WriteLine(item.Element+"="+item.Score); }

 RedisValue[] SortedSetRangeByRank(RedisKey key, long start = 0, long stop = -1, Order order =Order.Ascending) 根据打分排序返回值,可以根据序号查询其中一部分;

RedisValue[] SortedSetRangeByScore(RedisKey key, double start = double.NegativeInfinity, doublestop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1)

根据打分排序返回值,可以只返回 start- stop 这个范围的打分;

sortedset 应用场景:

1) 用户每搜一次一个关键词,就给这个关键词加一分;展示热搜的时候就把前 N 个获取出来就行了;

      2) 高积分用户排行榜;

      3) 热门商品;

       4) 给宝宝投票;

17、Hash

相当于 value 又是一个“键值对集合”或者值是另外一个 Dictionary。 没想到有什么应用场景。

18、Geo 类型

Geo 是 Redis 3.2 版本后新增的数据类型,用来保存兴趣点(POI,point of interest)的坐标信息。

可以实现计算两 POI 之间的距离、获取一个点周边指定距离的 POI。 下面添加兴趣点数据,”1”、”2”是点的主键,点的名称、地址、电话等存到其他表中。

db.GeoAdd("ShopsGeo", new GeoEntry(116.34039, 39.94218,"1"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.340934, 39.942221, "2"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.341082, 39.941025, "3"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.340848, 39.937758, "4"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.342982, 39.937325, "5"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.340866, 39.936827, "6"));

GeoRemove(RedisKey key, RedisValue member)删除一个点

查询两个 POI 之间的举例:double? dist = db.GeoDistance("ShopsGeo", "1", "5", GeoUnit.Meters);// 最后一个参数为距离单位根据点的主键获取坐标:GeoPosition? pos = db.GeoPosition("ShopsGeo", "1")

获取一个 POI 周边的 POI:

GeoRadiusResult[] results = db.GeoRadius("ShopsGeo", "2", 200, GeoUnit.Meters);//获取”2”这个周边 200 米范围内的 POI
foreach(GeoRadiusResult result in results)
{ Console.WriteLine("Id="+result.Member+",位置"+result.Position+",距离"+result.Distance); }

  获取一个坐标(这个坐标不一定是 POI)周边的 POI:

GeoRadiusResult[] results = db.GeoRadius("ShopsGeo", 116.34092, 39.94223, 200, GeoUnit.Meters);// 获 取(116.34092, 39.94223)这个周边 200 米范围内的 POI
foreach(GeoRadiusResult result in results)
{ Console.WriteLine("Id="+result.Member+",位置"+result.Position+",距离"+result.Distance); }

     Geo Hash 原理:http://www.cnblogs.com/LBSer/p/3310455.html

19、Redis 的批量操作

如果一次性操作很多,会很慢,那么可以使用批量操作,两种方式: 1)几乎所有的操作都支持数组类型,这样就可以一次性操作多条数据:比如

GeoAdd(RedisKey key, GeoEntry[] values)、SortedSetAdd(RedisKey key, SortedSetEntry[] values) 2) 如果一次性的操作不是简单的同类型操作,那么就要使用批量模式:
IBatch batch = db.CreateBatch();
db.GeoAdd("ShopsGeo1", new GeoEntry(116.34039, 39.94218, "1"));

db.StringSet("abc", "123");
batch.Execute();

会把当前连接的 CreateBatch()、Execute()之间的操作一次性提交给服务器。

20、redis 分布式锁

     多线程中的 lock 等的作用范围是当前的程序范围内的,如果想跨多台服务器的锁(尽量避免这样搞),就要使用分布式锁。

      

RedisValue token = Environment.MachineName;

//实际项目秒杀此处可换成商品 ID

if (db.LockTake("mylock", token, TimeSpan.FromSeconds(10)))//第三个参数为锁超时时间,锁占 用最多 10 秒钟,超过 10 秒钟如果还没有 LockRelease,则也自动释放锁,避免了死锁
{ try { } finally { db.LockRelease("mylock", token); } } else { Console.WriteLine("获得锁失败");
}

  

 

Redis 介绍学习的更多相关文章

  1. Redis 介绍与使用

    数据库主要类型有对象数据库,关系数据库,键值数据库等等,对象数据库太超前了,现阶段不提也罢:关系数据库就是平常说的MySQL,PostgreSQL这些熟的不能再熟的东西,至于键值数据库则是本文要着重说 ...

  2. 基于Python操作redis介绍

    (注:本文部分内容摘自互联网,由于作者水平有限,不足之处,还望留言指正.) 毕业前的最后一个学期(2016.03),龙哥结婚了.可是总有些人喜欢嘲笑别人,调侃我.当时我就理直气壮的告诉他们,等龙哥孩子 ...

  3. 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

    反射实现Model修改前后的内容对比   在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...

  4. Redis介绍、安装部署、操作

    学习连接:http://www.runoob.com/redis/redis-tutorial.html 一.Redis介绍 Redis是NoSql的一种. NoSql,全名:Not Only Sql ...

  5. Redis入门学习(学习过程记录)

    Redis(入门笔记) 学习一个大的技术点,然后顺带着就把这个技术点的面试题给学习了. 学习完一个技术后,如果面试题还不能够解答的话,只能说明学的不精,需要查漏补缺. 下一个学习的方向:Redis-非 ...

  6. Redis安全学习

    Redis安全学习 一直在听SSRF打Redis,那Redis到底是啥,正式的认真学习一下. 1.Redis是什么 REmote DIctionary Server(Redis) 是一个由Salvat ...

  7. Redis in Action : Redis 实战学习笔记

    1 1 1 Redis in Action : Redis  实战学习笔记 1 http://redis.io/ https://github.com/antirez/redis https://ww ...

  8. memcache/redis 缓存学习笔记

    0.redis和memcache的区别 a.redis可以存储除了string之外的对象,如list,hash等 b.服务器宕机以后,redis会把内存的数据持久化到磁盘上,而memcache则不会 ...

  9. Redis介绍以及安装(Linux)

    Redis介绍以及安装(Linux) redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcached类似,但很大程度补偿了memcached的不足,它支持存储的 ...

随机推荐

  1. Kafka源码分析及图解原理之Producer端

    一.前言 任何消息队列都是万变不离其宗都是3部分,消息生产者(Producer).消息消费者(Consumer)和服务载体(在Kafka中用Broker指代).那么本篇主要讲解Producer端,会有 ...

  2. 网络编程之TCP/IP各层详解

    网络编程之TCP/IP各层详解 我们将应用层,表示层,会话层并作应用层,从TCP/IP五层协议的角度来阐述每层的由来与功能,搞清楚了每层的主要协议,就理解了整个物联网通信的原理. 首先,用户感知到的只 ...

  3. Netty源码分析 (七)----- read过程 源码分析

    在上一篇文章中,我们分析了processSelectedKey这个方法中的accept过程,本文将分析一下work线程中的read过程. private static void processSele ...

  4. 060 Python必备库-从数据处理到人工智能

    目录 一.概述 1.1 从数据处理到人工智能 二.Python库之数据分析 2.1 numpy 2.2 pandas 2.3 scipy 三.Python库之数据可视化 3.1 matplotlib ...

  5. 洛谷 P1525 关押罪犯 NOIp2010提高组 (贪心+并查集)

    题目链接:https://www.luogu.org/problemnew/show/P1525 题目分析 通过分析,我们可以知道,这道题的抽象意义就是把一个带边权的无向图,分成两个点集,使得两个集合 ...

  6. GlusterFs卷类型分析及创建、使用(结合kubernetes集群分析)

    引言 本文通过对卷类型的分析对比,来帮助读者选取生产环境最符合服务的挂载存储,命令可结合<glusterfs详解及kubernetes 搭建heketi-glusterfs>进行实验,下面 ...

  7. 关于Oracle12c中无scott用户的问题

    我目前预习是通过视频,学到此处视频里的老师要登录scott用户,而我无法登陆,显示用户不存在,虽然在Oracle文件中也可以找到scott.sql文件,但经过网上教程创建用户后我觉得很麻烦而且没有成功 ...

  8. out.print()与response.sendRedirect()

    这样的情况下 out.print("<script>alert('非法操作,请重新登录!');</script>"); response.sendRedir ...

  9. ACM卡常数(各种玄学优化)

    首先声明,本博文部分内容仅仅适用于ACM竞赛,并不适用于NOIP与OI竞赛,违规使用可能会遭竞赛处理,请慎重使用!遭遇任何情况都与本人无关哈=7= 我也不想搞得那么严肃的,但真的有些函数在NOIP与O ...

  10. Flink1.9整合Kafka

    本文基于Flink1.9版本简述如何连接Kafka. 流式连接器 我们知道可以自己来开发Source 和 Sink ,但是一些比较基本的 Source 和 Sink 已经内置在 Flink 里. 预定 ...