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("获得锁失败");
- }