第四节:Geo类型介绍以及Redis批量操作、事务、分布式锁
一. Geo类型
1. 类型说明
Geo 是 Redis 3.2 版本后新增的数据类型,用来保存兴趣点(POI,point of interest)的坐标信息。可以实现计算两 POI 之间的距离、获取一个点周边指定距离的 POI。
2. 常用Api
(1).GeoAdd:添加POI点
(2).GeoDistance:获取两点之间的最短距离
(3).GeoPosition:获取某个点的坐标
(4).GeoRadius:获取某个点(不一定是POI)周边xx米以外的点
(5).GeoRemove:删除某个点
代码分享:
//1. 添加所有商店的地理位置
db.GeoAdd("ShopsGeo", new GeoEntry(116.34039, 39.94218, "name1"));
db.GeoAdd("ShopsGeo", new GeoEntry(116.340934, 39.942221, "name2"));
db.GeoAdd("ShopsGeo", new GeoEntry(116.341082, 39.941025, "name3"));
db.GeoAdd("ShopsGeo", new GeoEntry(116.340848, 39.937758, "name4"));
db.GeoAdd("ShopsGeo", new GeoEntry(116.342982, 39.937325, "name5"));
db.GeoAdd("ShopsGeo", new GeoEntry(116.340866, 39.936827, "name6")); //2. 计算商店name1和name2之间的距离(单位m)
double? dist = db.GeoDistance("ShopsGeo", "name1", "name5", GeoUnit.Meters); //3. 获取name1商店的坐标
GeoPosition? pos = db.GeoPosition("ShopsGeo", "name1"); //4. 获取一个 name2 周边的200内的点:
GeoRadiusResult[] results = db.GeoRadius("ShopsGeo", "name2", , GeoUnit.Meters);
foreach (GeoRadiusResult result in results)
{
Console.WriteLine("Id=" + result.Member + ",位置" + result.Position + ",距离" + result.Distance);
} //5. 获取一个坐标(116.34092, 39.94223)(这个坐标不一定是 POI)周边的 POI:
GeoRadiusResult[] results2 = db.GeoRadius("ShopsGeo", 116.34092, 39.94223, , GeoUnit.Meters);
foreach (GeoRadiusResult result in results2)
{
Console.WriteLine("Id=" + result.Member + ",位置" + result.Position + ",距离" + result.Distance);
} //6. 删除
bool d1 = db.GeoRemove("ShopsGeo", "name2");
3. 案例
地图上点相关的操作,方圆xx米内有多少个商店,某两个商店间的距离
二. Redis批量操作和事务
1. 批量操作
Batch会把所需要执行的命令打包成一条请求发到Redis,然后一起等待返回结果。这样批量操作的速度就大大提升。 利用CreateBatch和Execute方法,仅支持异步方法哦。
public static void BatchDemo(IDatabase db)
{
IBatch batch = db.CreateBatch();
batch.StringSetAsync("keen1", "");
batch.StringSetAsync("keen2", "");
batch.Execute(); }
2. 事务
Redis的操作都是原子性单线程的,如果一次性操作很多,基本上每个方法都支持批量操作,但是如果操作的数据类型不同,可以使用Redis的事务进行包裹。 CreateTransaction和Execute方法
public static void TransDemo(IDatabase db)
{
var trans = db.CreateTransaction();
trans.StringSetAsync("keen1", "");
trans.StringSetAsync("keen2", );
bool result = trans.Execute();
}
3. 区别
批量操作假设里面有一个出错,不会整体回滚,而事务要么都成功,要么都失败。
三. Redis分布式锁
1. 背景
在传统的单体项目中,即部署到单个IIS上,针对并发问题,比如进销存中的出库和入库问题,多个人同时操作,属于一个IIS进程中多个线程并发操作的问题,这个时候可以引入线程锁lock/Monitor等,轻松解决这类问题。但是随着业务量的逐渐增大,比如"秒杀业务",肯定是集群,这个时候线程锁已经没用了,必须引入分布式锁。
常见的分布式锁有:数据库、zookeeper、redis。
2. 技术分析
秒杀业务集群同时访问DB,很容易出现超买超卖问题,如下图:

分析:

解决方案:
在秒杀服务集群和DB之间引入Redis(或者Redis集群),无论是Redis单体还是集群,分布式锁都是上一个解锁了下一个才继续加锁,引入Redis集群的目的是防止Redis崩溃,而不是加快速度,这样保证了最终到DB上上的操作是按顺序依次进行的,从而解决了超卖问题。如下图:

3. 代码实战
StackExchange.Redis中加锁和解锁的api分别是:LockTake和LockRelease。 bool LockTake(RedisKey key, RedisValue value, TimeSpan expiry, CommandFlags flags = CommandFlags.None); 三个参数的含义分别是:
(1). 锁名
(2). 谁加的的锁
(3). 超时时间,过期自动释放,防止死锁。
代码如下:(加锁的时候要循环获取锁,直到获取为止)
/// <summary>
/// 分布式锁 业务
/// </summary>
/// <param name="db"></param>
public static void DfsLockDemo(IDatabase db)
{ Lock(db);
try
{
Console.WriteLine("业务执行中......");
Thread.Sleep();
Console.WriteLine("业务执行完毕");
}
catch (Exception)
{
//释放锁
UnLock(db);
}
finally
{
//释放锁
UnLock(db);
}
} /// <summary>
/// 加锁
/// </summary>
/// <param name="db"></param>
public static void Lock(IDatabase db)
{
RedisValue token = Environment.MachineName;
while (true)
{
bool flag = db.LockTake("myLock", token, TimeSpan.FromSeconds()); //10秒后自动释放
if (flag)
{
//表示获取成功,跳出while
break;
}
else
{
Console.WriteLine("获取失败,继续获取");
Thread.Sleep(); }
}
}
/// <summary>
/// 解锁
/// </summary>
/// <param name="db"></param>
public static void UnLock(IDatabase db)
{
RedisValue token = Environment.MachineName;
db.LockRelease("myLock", token);
}
模拟两个项目运行效果:

秒杀案例其它思路或者详细解决方案见: 第六节:秒杀业务/超买超卖的几种解决思路
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
第四节:Geo类型介绍以及Redis批量操作、事务、分布式锁的更多相关文章
- redis客户端、分布式锁及数据一致性
Redis Java客户端有很多的开源产品比如Redission.Jedis.lettuce等. Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持:Redis ...
- redis系列:分布式锁
redis系列:分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- 基于Redis的简单分布式锁的原理
参考资料:https://redis.io/commands/setnx 加锁是为了解决多线程的资源共享问题.Java中,单机环境的锁可以用synchronized和Lock,其他语言也都应该有自己的 ...
- redis事务,分布式锁
事务:一组命令集合 主要命令multi 和exec multi set a 1 sadd s1 a ...... exec 错误处理 (1)语法错误 127.0.0.1:6379> multi ...
- 如何用redis正确实现分布式锁?
先把结论抛出来:redis无法正确实现分布式锁!即使是redis单节点也不行!redis的所谓分布式锁无法用在对锁要求严格的场景下,比如:同一个时间点只能有一个客户端获取锁. 首先来看下单节点下一般r ...
- Redis高并发分布式锁详解
为什么需要分布式锁 1.为了解决Java共享内存模型带来的线程安全问题,我们可以通过加锁来保证资源访问的单一,如JVM内置锁synchronized,类级别的锁ReentrantLock. 2.但是随 ...
- 基于redis实现的分布式锁
基于redis实现的分布式锁 我们知道,在多线程环境中,锁是实现共享资源互斥访问的重要机制,以保证任何时刻只有一个线程在访问共享资源.锁的基本原理是:用一个状态值表示锁,对锁的占用和释放通过状态值来标 ...
- 一个Redis实现的分布式锁
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.conne ...
- Redis系列(二)--分布式锁、分布式ID简单实现及思路
分布式锁: Redis可以实现分布式锁,只是讨论Redis的实现思路,而真的实现分布式锁,Zookeeper更加可靠 为什么使用分布式锁: 单机环境下只存在多线程,通过同步操作就可以实现对并发环境的安 ...
随机推荐
- 分词 | 双向匹配中文分词算法python实现
本次实验内容是基于词典的双向匹配算法的中文分词算法的实现.使用正向和反向最大匹配算法对给定句子进行分词,对得到的结果进行比较,从而决定正确的分词方法. 算法描述正向最大匹配算法先设定扫描的窗口大小ma ...
- centos7下mysql5.7的安装与配置
centos7下MySQL5.7的安装与配置 下载 下载地址 根据系统和版本选择红框中的四个RPM包下载即可,然后放到centos7系统中的/opt目录下,等待稍后安装. 安装前的准备 1. 检查系统 ...
- http服务源码分析
多读go的源码,可以加深对go语言的理解和认知,今天分享一下http相关的源码部分 在不使用第三方库的情况下,我们可以很容易的的用go实现一个http服务, package main import ( ...
- Disruptor系列(二)— disruptor使用
本文译自Dirsruptor在github上的wiki中文章:Getting Started 获取Disruptor Disruptor jar包可以从maven仓库mvnrepository获取,可 ...
- solidity 智能合约之间的调用
智能合约之间的调用 在区块链上,有些功能往往无法通过一个智能合约完成,此时便会用到智能合约之间的调用.本篇文章带大家通过具体示例来了解一下智能合约之间的调用. 在智能合约的编译过程中,有两种情况:调用 ...
- Vue实现简单的列表金额计算效果(简易购物车)
效果图: 使用技术:v-for v-bind v-on实现简单的列表选中绑定操作 代码: <!DOCTYPE html> <html> <head> <met ...
- Protobuffer学习文档
官方EN:https://developers.google.com/protocol-buffers/docs/pythontutorial 中文:https://cloud.tencent.com ...
- idea的service注入mapper报错
一.问题 idea的java项目中,service类中注入mapper报错 二.解决 方法1 在mapper类上加上 @Repository 注解即可,当然不加也行,程序也不回报错,是idea的误报 ...
- DataGridView中的rows.Count比实际行数多1的原因以及解决办法
场景 DataGridView怎样实现添加.删除.上移.下移一行: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10281414 ...
- 使用Dynamics 365 CE Web API查询数据加点料及选项集字段常用查询
微软动态CRM专家罗勇 ,回复336或者20190516可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me. 紧接上文:配置Postman通过OAuth 2 implicit ...