RedisHelper.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using Newtonsoft.Json;
  7. using StackExchange.Redis;
  8. namespace Masuit.Tools.NoSQL
  9. {
  10. /// <summary>
  11. /// Redis操作
  12. /// </summary>
  13. public class RedisHelper : IDisposable
  14. {
  15. private int DbNum { get; }
  16. private readonly ConnectionMultiplexer _conn;
  17. /// <summary>
  18. /// Redis服务器连接字符串,默认为:127.0.0.1:6379,allowadmin=true<br/>
  19. /// </summary>
  20. public static string RedisConnectionString
  21. {
  22. get => "127.0.0.1:6379,allowadmin=true";
  23. set { }
  24. }
  25. /// <summary>
  26. /// 自定义键
  27. /// </summary>
  28. public string CustomKey;
  29. /// <summary>
  30. /// 连接失败 , 如果重新连接成功你将不会收到这个通知
  31. /// </summary>
  32. public event EventHandler<ConnectionFailedEventArgs> ConnectionFailed;
  33. /// <summary>
  34. /// 重新建立连接之前的错误
  35. /// </summary>
  36. public event EventHandler<ConnectionFailedEventArgs> ConnectionRestored;
  37. /// <summary>
  38. /// 发生错误时
  39. /// </summary>
  40. public event EventHandler<RedisErrorEventArgs> ErrorMessage;
  41. /// <summary>
  42. /// 配置更改时
  43. /// </summary>
  44. public event EventHandler<EndPointEventArgs> ConfigurationChanged;
  45. /// <summary>
  46. /// 更改集群时
  47. /// </summary>
  48. public event EventHandler<HashSlotMovedEventArgs> HashSlotMoved;
  49. /// <summary>
  50. /// redis类库错误时
  51. /// </summary>
  52. public event EventHandler<InternalErrorEventArgs> InternalError;
  53. /// <summary>
  54. /// 静态连接池
  55. /// </summary>
  56. public static ConcurrentDictionary<string, ConnectionMultiplexer> ConnectionCache { get; set; } = new ConcurrentDictionary<string, ConnectionMultiplexer>();
  57. #region 构造函数
  58. /// <summary>
  59. /// 构造函数,使用该构造函数需要先在config中配置链接字符串,连接字符串在config配置文件中的ConnectionStrings节下配置,name固定为RedisHosts,值的格式:127.0.0.1:6379,allowadmin=true,若未正确配置,将按默认值“127.0.0.1:6379,allowadmin=true”进行操作,如:<br/>
  60. /// &lt;connectionStrings&gt;<br/>
  61. /// &lt;add name = "RedisHosts" connectionString="127.0.0.1:6379,allowadmin=true"/&gt;<br/>
  62. /// &lt;/connectionStrings&gt;
  63. /// </summary>
  64. /// <param name="dbNum">数据库编号</param>
  65. public RedisHelper(int dbNum = 0) : this(null, dbNum)
  66. {
  67. }
  68. /// <summary>
  69. /// 构造函数
  70. /// </summary>
  71. /// <param name="readWriteHosts">Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true</param>
  72. /// <param name="dbNum">数据库的编号</param>
  73. public RedisHelper(string readWriteHosts, int dbNum = 0)
  74. {
  75. DbNum = dbNum;
  76. _conn = string.IsNullOrWhiteSpace(readWriteHosts) ? ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(RedisConnectionString)) : ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(readWriteHosts));
  77. //_conn.ConfigurationChanged += MuxerConfigurationChanged;
  78. _conn.ConfigurationChanged += ConfigurationChanged;
  79. //_conn.ConnectionFailed += MuxerConnectionFailed;
  80. _conn.ConnectionFailed += ConnectionFailed;
  81. //_conn.ConnectionRestored += MuxerConnectionRestored;
  82. _conn.ConnectionRestored += ConnectionRestored;
  83. //_conn.ErrorMessage += MuxerErrorMessage;
  84. _conn.ErrorMessage += ErrorMessage;
  85. //_conn.HashSlotMoved += MuxerHashSlotMoved;
  86. _conn.HashSlotMoved += HashSlotMoved;
  87. //_conn.InternalError += MuxerInternalError;
  88. _conn.InternalError += InternalError;
  89. }
  90. /// <summary>
  91. /// 构造函数
  92. /// </summary>
  93. /// <param name="readWriteHosts">Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true</param>
  94. /// <param name="dbNum">数据库的编号</param>
  95. private RedisHelper(string readWriteHosts, int dbNum, int _)
  96. {
  97. DbNum = dbNum;
  98. readWriteHosts = string.IsNullOrWhiteSpace(readWriteHosts) ? RedisConnectionString : readWriteHosts;
  99. _conn = ConnectionCache.GetOrAdd(readWriteHosts, ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(readWriteHosts)));
  100. //_conn.ConfigurationChanged += MuxerConfigurationChanged;
  101. _conn.ConfigurationChanged += ConfigurationChanged;
  102. //_conn.ConnectionFailed += MuxerConnectionFailed;
  103. _conn.ConnectionFailed += ConnectionFailed;
  104. //_conn.ConnectionRestored += MuxerConnectionRestored;
  105. _conn.ConnectionRestored += ConnectionRestored;
  106. //_conn.ErrorMessage += MuxerErrorMessage;
  107. _conn.ErrorMessage += ErrorMessage;
  108. //_conn.HashSlotMoved += MuxerHashSlotMoved;
  109. _conn.HashSlotMoved += HashSlotMoved;
  110. //_conn.InternalError += MuxerInternalError;
  111. _conn.InternalError += InternalError;
  112. }
  113. /// <summary>
  114. /// 获取新实例
  115. /// </summary>
  116. /// <param name="db">数据库的编号</param>
  117. /// <returns></returns>
  118. public static RedisHelper GetInstance(int db = 0)
  119. {
  120. return new RedisHelper(db);
  121. }
  122. /// <summary>
  123. /// 获取单例
  124. /// </summary>
  125. /// <param name="db">数据库的编号</param>
  126. /// <returns></returns>
  127. public static RedisHelper GetSingleInstance(int db = 0)
  128. {
  129. return new RedisHelper(null, db, 0);
  130. }
  131. /// <summary>
  132. /// 从对象池获取默认实例
  133. /// </summary>
  134. /// <param name="conn">Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true</param>
  135. /// <param name="db">数据库的编号</param>
  136. /// <returns></returns>
  137. public static RedisHelper GetInstance(string conn, int db = 0)
  138. {
  139. return new RedisHelper(conn, db);
  140. }
  141. /// <summary>
  142. /// 获取单例
  143. /// </summary>
  144. /// <param name="conn">Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true</param>
  145. /// <param name="db">数据库的编号</param>
  146. /// <returns></returns>
  147. public static RedisHelper GetSingleInstance(string conn, int db = 0)
  148. {
  149. return new RedisHelper(conn, db, 0);
  150. }
  151. #endregion 构造函数
  152. #region String
  153. #region 同步方法
  154. /// <summary>
  155. /// 保存单个key value
  156. /// </summary>
  157. /// <param name="key">Redis Key</param>
  158. /// <param name="value">保存的值</param>
  159. /// <param name="expiry">过期时间</param>
  160. /// <returns>是否保存成功</returns>
  161. public bool SetString(string key, string value, TimeSpan? expiry = default(TimeSpan?))
  162. {
  163. key = AddSysCustomKey(key);
  164. return Do(db => db.StringSet(key, value, expiry));
  165. }
  166. /// <summary>
  167. /// 保存多个key value
  168. /// </summary>
  169. /// <param name="keyValues">键值对</param>
  170. /// <returns>是否保存成功</returns>
  171. public bool SetString(List<KeyValuePair<RedisKey, RedisValue>> keyValues)
  172. {
  173. List<KeyValuePair<RedisKey, RedisValue>> newkeyValues =
  174. keyValues.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToList();
  175. return Do(db => db.StringSet(newkeyValues.ToArray()));
  176. }
  177. /// <summary>
  178. /// 保存一个对象
  179. /// </summary>
  180. /// <typeparam name="T">对象类型</typeparam>
  181. /// <param name="key">键</param>
  182. /// <param name="obj">值</param>
  183. /// <param name="expiry">过期时间</param>
  184. /// <returns>是否保存成功</returns>
  185. public bool SetString<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
  186. {
  187. key = AddSysCustomKey(key);
  188. string json = ConvertJson(obj);
  189. return Do(db => db.StringSet(key, json, expiry));
  190. }
  191. /// <summary>
  192. /// 获取单个key的值
  193. /// </summary>
  194. /// <param name="key">键</param>
  195. /// <returns>值</returns>
  196. public string GetString(string key)
  197. {
  198. if (KeyExists(key))
  199. {
  200. key = AddSysCustomKey(key);
  201. return Do(db => db.StringGet(key));
  202. }
  203. return string.Empty;
  204. }
  205. /// <summary>
  206. /// 获取多个Key
  207. /// </summary>
  208. /// <param name="listKey">键集合</param>
  209. /// <returns>值集合</returns>
  210. public RedisValue[] GetString(List<string> listKey)
  211. {
  212. List<string> newKeys = listKey.Select(AddSysCustomKey).ToList();
  213. return Do(db => db.StringGet(ConvertRedisKeys(newKeys)));
  214. }
  215. /// <summary>
  216. /// 获取一个key的对象
  217. /// </summary>
  218. /// <typeparam name="T">数据类型</typeparam>
  219. /// <param name="key">键</param>
  220. /// <returns>实例对象</returns>
  221. public T GetString<T>(string key)
  222. {
  223. if (KeyExists(key))
  224. {
  225. key = AddSysCustomKey(key);
  226. return Do(db => ConvertObj<T>(db.StringGet(key)));
  227. }
  228. return default(T);
  229. }
  230. /// <summary>
  231. /// 为数字增长val
  232. /// </summary>
  233. /// <param name="key">键</param>
  234. /// <param name="val">可以为负</param>
  235. /// <returns>增长后的值</returns>
  236. public double StringIncrement(string key, double val = 1)
  237. {
  238. key = AddSysCustomKey(key);
  239. return Do(db => db.StringIncrement(key, val));
  240. }
  241. /// <summary>
  242. /// 为数字减少val
  243. /// </summary>
  244. /// <param name="key">键</param>
  245. /// <param name="val">可以为负</param>
  246. /// <returns>减少后的值</returns>
  247. public double StringDecrement(string key, double val = 1)
  248. {
  249. key = AddSysCustomKey(key);
  250. return Do(db => db.StringDecrement(key, val));
  251. }
  252. #endregion 同步方法
  253. #region 异步方法
  254. /// <summary>
  255. /// 保存单个key value
  256. /// </summary>
  257. /// <param name="key">Redis Key</param>
  258. /// <param name="value">保存的值</param>
  259. /// <param name="expiry">过期时间</param>
  260. /// <returns>是否保存成功</returns>
  261. public async Task<bool> SetStringAsync(string key, string value, TimeSpan? expiry = default(TimeSpan?))
  262. {
  263. key = AddSysCustomKey(key);
  264. return await Do(db => db.StringSetAsync(key, value, expiry));
  265. }
  266. /// <summary>
  267. /// 保存多个key value
  268. /// </summary>
  269. /// <param name="keyValues">键值对</param>
  270. /// <returns>是否保存成功</returns>
  271. public async Task<bool> SetStringAsync(List<KeyValuePair<RedisKey, RedisValue>> keyValues)
  272. {
  273. List<KeyValuePair<RedisKey, RedisValue>> newkeyValues =
  274. keyValues.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToList();
  275. return await Do(db => db.StringSetAsync(newkeyValues.ToArray()));
  276. }
  277. /// <summary>
  278. /// 保存一个对象
  279. /// </summary>
  280. /// <typeparam name="T">数据类型</typeparam>
  281. /// <param name="key">键</param>
  282. /// <param name="obj">需要被缓存的对象</param>
  283. /// <param name="expiry">过期时间</param>
  284. /// <returns>是否保存成功</returns>
  285. public async Task<bool> SetStringAsync<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
  286. {
  287. key = AddSysCustomKey(key);
  288. string json = ConvertJson(obj);
  289. return await Do(db => db.StringSetAsync(key, json, expiry));
  290. }
  291. /// <summary>
  292. /// 获取单个key的值
  293. /// </summary>
  294. /// <param name="key">键</param>
  295. /// <returns>值</returns>
  296. public async Task<string> GetStringAsync(string key)
  297. {
  298. if (KeyExists(key))
  299. {
  300. key = AddSysCustomKey(key);
  301. return await Do(db => db.StringGetAsync(key));
  302. }
  303. return string.Empty;
  304. }
  305. /// <summary>
  306. /// 获取多个Key
  307. /// </summary>
  308. /// <param name="listKey">键集合</param>
  309. /// <returns>值集合</returns>
  310. public Task<RedisValue[]> GetStringAsync(List<string> listKey)
  311. {
  312. List<string> newKeys = listKey.Select(AddSysCustomKey).ToList();
  313. return Do(db => db.StringGetAsync(ConvertRedisKeys(newKeys)));
  314. }
  315. /// <summary>
  316. /// 获取一个key的对象
  317. /// </summary>
  318. /// <typeparam name="T">数据类型</typeparam>
  319. /// <param name="key">键</param>
  320. /// <returns>实例对象</returns>
  321. public async Task<T> GetStringAsync<T>(string key)
  322. {
  323. if (KeyExists(key))
  324. {
  325. key = AddSysCustomKey(key);
  326. string result = await Do(db => db.StringGetAsync(key));
  327. return ConvertObj<T>(result);
  328. }
  329. return default(T);
  330. }
  331. /// <summary>
  332. /// 为数字增长val
  333. /// </summary>
  334. /// <param name="key">键</param>
  335. /// <param name="val">可以为负</param>
  336. /// <returns>增长后的值</returns>
  337. public Task<double> IncrementStringAsync(string key, double val = 1)
  338. {
  339. key = AddSysCustomKey(key);
  340. return Do(db => db.StringIncrementAsync(key, val));
  341. }
  342. /// <summary>
  343. /// 为数字减少val
  344. /// </summary>
  345. /// <param name="key">键</param>
  346. /// <param name="val">可以为负</param>
  347. /// <returns>减少后的值</returns>
  348. public Task<double> DecrementStringAsync(string key, double val = 1)
  349. {
  350. key = AddSysCustomKey(key);
  351. return Do(db => db.StringDecrementAsync(key, val));
  352. }
  353. #endregion 异步方法
  354. #endregion String
  355. #region Hash
  356. #region 同步方法
  357. /// <summary>
  358. /// 判断某个数据是否已经被缓存
  359. /// </summary>
  360. /// <param name="key">键</param>
  361. /// <param name="dataKey">对象的字段</param>
  362. /// <returns>是否缓存成功</returns>
  363. public bool HashExists(string key, string dataKey)
  364. {
  365. key = AddSysCustomKey(key);
  366. return Do(db => db.HashExists(key, dataKey));
  367. }
  368. /// <summary>
  369. /// 存储数据到hash表
  370. /// </summary>
  371. /// <typeparam name="T">数据类型</typeparam>
  372. /// <param name="key">键</param>
  373. /// <param name="dataKey">对象的字段</param>
  374. /// <param name="t">对象实例</param>
  375. /// <returns>是否存储成功</returns>
  376. public bool SetHash<T>(string key, string dataKey, T t)
  377. {
  378. key = AddSysCustomKey(key);
  379. return Do(db =>
  380. {
  381. string json = ConvertJson(t);
  382. return db.HashSet(key, dataKey, json);
  383. });
  384. }
  385. /// <summary>
  386. /// 移除hash中的某值
  387. /// </summary>
  388. /// <param name="key">键</param>
  389. /// <param name="dataKey">对象的字段</param>
  390. /// <returns>是否移除成功</returns>
  391. public bool DeleteHash(string key, string dataKey)
  392. {
  393. key = AddSysCustomKey(key);
  394. return Do(db => db.HashDelete(key, dataKey));
  395. }
  396. /// <summary>
  397. /// 移除hash中的多个值
  398. /// </summary>
  399. /// <param name="key">键</param>
  400. /// <param name="dataKeys">对象的字段集合</param>
  401. /// <returns>数量</returns>
  402. public long DeleteHash(string key, List<RedisValue> dataKeys)
  403. {
  404. key = AddSysCustomKey(key);
  405. //List<RedisValue> dataKeys1 = new List<RedisValue>() {"1","2"};
  406. return Do(db => db.HashDelete(key, dataKeys.ToArray()));
  407. }
  408. /// <summary>
  409. /// 从hash表获取数据
  410. /// </summary>
  411. /// <typeparam name="T">数据类型</typeparam>
  412. /// <param name="key">键</param>
  413. /// <param name="dataKey">对象的字段</param>
  414. /// <returns>对象实例</returns>
  415. public T GetHash<T>(string key, string dataKey)
  416. {
  417. if (KeyExists(key))
  418. {
  419. key = AddSysCustomKey(key);
  420. return Do(db =>
  421. {
  422. string value = db.HashGet(key, dataKey);
  423. return ConvertObj<T>(value);
  424. });
  425. }
  426. return default(T);
  427. }
  428. /// <summary>
  429. /// 为数字增长val
  430. /// </summary>
  431. /// <param name="key">键</param>
  432. /// <param name="dataKey">对象的字段</param>
  433. /// <param name="val">可以为负</param>
  434. /// <returns>增长后的值</returns>
  435. public double IncrementHash(string key, string dataKey, double val = 1)
  436. {
  437. key = AddSysCustomKey(key);
  438. return Do(db => db.HashIncrement(key, dataKey, val));
  439. }
  440. /// <summary>
  441. /// 为数字减少val
  442. /// </summary>
  443. /// <param name="key">键</param>
  444. /// <param name="dataKey">对象的字段</param>
  445. /// <param name="val">可以为负</param>
  446. /// <returns>减少后的值</returns>
  447. public double DecrementHash(string key, string dataKey, double val = 1)
  448. {
  449. key = AddSysCustomKey(key);
  450. return Do(db => db.HashDecrement(key, dataKey, val));
  451. }
  452. /// <summary>
  453. /// 获取hashkey所有Redis key
  454. /// </summary>
  455. /// <typeparam name="T">数据类型</typeparam>
  456. /// <param name="key">键</param>
  457. /// <returns>数据集合</returns>
  458. public List<T> HashKeys<T>(string key)
  459. {
  460. key = AddSysCustomKey(key);
  461. return Do(db =>
  462. {
  463. RedisValue[] values = db.HashKeys(key);
  464. return ConvetList<T>(values);
  465. });
  466. }
  467. #endregion 同步方法
  468. #region 异步方法
  469. /// <summary>
  470. /// 判断某个数据是否已经被缓存
  471. /// </summary>
  472. /// <param name="key">键</param>
  473. /// <param name="dataKey">对象的字段</param>
  474. /// <returns>是否缓存成功</returns>
  475. public Task<bool> ExistsHashAsync(string key, string dataKey)
  476. {
  477. key = AddSysCustomKey(key);
  478. return Do(db => db.HashExistsAsync(key, dataKey));
  479. }
  480. /// <summary>
  481. /// 存储数据到hash表
  482. /// </summary>
  483. /// <typeparam name="T">数据类型</typeparam>
  484. /// <param name="key">键</param>
  485. /// <param name="dataKey">对象的字段</param>
  486. /// <param name="t">对象实例</param>
  487. /// <returns>是否存储成功</returns>
  488. public Task<bool> SetHashAsync<T>(string key, string dataKey, T t)
  489. {
  490. key = AddSysCustomKey(key);
  491. return Do(db =>
  492. {
  493. string json = ConvertJson(t);
  494. return db.HashSetAsync(key, dataKey, json);
  495. });
  496. }
  497. /// <summary>
  498. /// 移除hash中的某值
  499. /// </summary>
  500. /// <param name="key">键</param>
  501. /// <param name="dataKey">对象的字段</param>
  502. /// <returns>是否移除成功</returns>
  503. public Task<bool> DeleteHashAsync(string key, string dataKey)
  504. {
  505. key = AddSysCustomKey(key);
  506. return Do(db => db.HashDeleteAsync(key, dataKey));
  507. }
  508. /// <summary>
  509. /// 移除hash中的多个值
  510. /// </summary>
  511. /// <param name="key">键</param>
  512. /// <param name="dataKeys">对象的字段集合</param>
  513. /// <returns>数量</returns>
  514. public Task<long> DeleteHashAsync(string key, List<RedisValue> dataKeys)
  515. {
  516. key = AddSysCustomKey(key);
  517. return Do(db => db.HashDeleteAsync(key, dataKeys.ToArray()));
  518. }
  519. /// <summary>
  520. /// 从hash表获取数据
  521. /// </summary>
  522. /// <typeparam name="T">数据类型</typeparam>
  523. /// <param name="key">键</param>
  524. /// <param name="dataKey">对象的字段</param>
  525. /// <returns>对象实例</returns>
  526. public async Task<T> GetHashAsync<T>(string key, string dataKey)
  527. {
  528. if (KeyExists(key))
  529. {
  530. key = AddSysCustomKey(key);
  531. string value = await Do(db => db.HashGetAsync(key, dataKey));
  532. return ConvertObj<T>(value);
  533. }
  534. return default(T);
  535. }
  536. /// <summary>
  537. /// 为数字增长val
  538. /// </summary>
  539. /// <param name="key">键</param>
  540. /// <param name="dataKey">对象的字段</param>
  541. /// <param name="val">可以为负</param>
  542. /// <returns>增长后的值</returns>
  543. public Task<double> IncrementHashAsync(string key, string dataKey, double val = 1)
  544. {
  545. key = AddSysCustomKey(key);
  546. return Do(db => db.HashIncrementAsync(key, dataKey, val));
  547. }
  548. /// <summary>
  549. /// 为数字减少val
  550. /// </summary>
  551. /// <param name="key">键</param>
  552. /// <param name="dataKey">对象的字段</param>
  553. /// <param name="val">可以为负</param>
  554. /// <returns>减少后的值</returns>
  555. public Task<double> DecrementHashAsync(string key, string dataKey, double val = 1)
  556. {
  557. key = AddSysCustomKey(key);
  558. return Do(db => db.HashDecrementAsync(key, dataKey, val));
  559. }
  560. /// <summary>
  561. /// 获取hashkey所有Redis key
  562. /// </summary>
  563. /// <typeparam name="T">数据类型</typeparam>
  564. /// <param name="key">键</param>
  565. /// <returns>数据集合</returns>
  566. public async Task<List<T>> HashKeysAsync<T>(string key)
  567. {
  568. key = AddSysCustomKey(key);
  569. RedisValue[] values = await Do(db => db.HashKeysAsync(key));
  570. return ConvetList<T>(values);
  571. }
  572. #endregion 异步方法
  573. #endregion Hash
  574. #region List
  575. #region 同步方法
  576. /// <summary>
  577. /// 移除指定ListId的内部List的值
  578. /// </summary>
  579. /// <typeparam name="T">数据类型</typeparam>
  580. /// <param name="key">键</param>
  581. /// <param name="value">值</param>
  582. public void RemoveList<T>(string key, T value)
  583. {
  584. key = AddSysCustomKey(key);
  585. Do(db => db.ListRemove(key, ConvertJson(value)));
  586. }
  587. /// <summary>
  588. /// 获取指定key的List
  589. /// </summary>
  590. /// <typeparam name="T">数据类型</typeparam>
  591. /// <param name="key">键</param>
  592. /// <returns>数据集</returns>
  593. public List<T> ListRange<T>(string key)
  594. {
  595. if (KeyExists(key))
  596. {
  597. key = AddSysCustomKey(key);
  598. return Do(redis =>
  599. {
  600. var values = redis.ListRange(key);
  601. return ConvetList<T>(values);
  602. });
  603. }
  604. return new List<T>();
  605. }
  606. /// <summary>
  607. /// 入队
  608. /// </summary>
  609. /// <typeparam name="T">数据类型</typeparam>
  610. /// <param name="key">键</param>
  611. /// <param name="value">值</param>
  612. public void ListRightPush<T>(string key, T value)
  613. {
  614. key = AddSysCustomKey(key);
  615. Do(db => db.ListRightPush(key, ConvertJson(value)));
  616. }
  617. /// <summary>
  618. /// 出队
  619. /// </summary>
  620. /// <typeparam name="T">数据类型</typeparam>
  621. /// <param name="key">键</param>
  622. /// <returns>值</returns>
  623. public T ListRightPop<T>(string key)
  624. {
  625. if (KeyExists(key))
  626. {
  627. key = AddSysCustomKey(key);
  628. return Do(db =>
  629. {
  630. var value = db.ListRightPop(key);
  631. return ConvertObj<T>(value);
  632. });
  633. }
  634. return default(T);
  635. }
  636. /// <summary>
  637. /// 入栈
  638. /// </summary>
  639. /// <typeparam name="T">数据类型</typeparam>
  640. /// <param name="key">键</param>
  641. /// <param name="value">值</param>
  642. public void ListLeftPush<T>(string key, T value)
  643. {
  644. key = AddSysCustomKey(key);
  645. Do(db => db.ListLeftPush(key, ConvertJson(value)));
  646. }
  647. /// <summary>
  648. /// 出栈
  649. /// </summary>
  650. /// <typeparam name="T">数据类型</typeparam>
  651. /// <param name="key">键</param>
  652. /// <returns>对象实例</returns>
  653. public T ListLeftPop<T>(string key)
  654. {
  655. if (KeyExists(key))
  656. {
  657. key = AddSysCustomKey(key);
  658. return Do(db =>
  659. {
  660. var value = db.ListLeftPop(key);
  661. return ConvertObj<T>(value);
  662. });
  663. }
  664. return default(T);
  665. }
  666. /// <summary>
  667. /// 获取集合中的数量
  668. /// </summary>
  669. /// <param name="key">键</param>
  670. /// <returns>数量</returns>
  671. public long ListLength(string key)
  672. {
  673. key = AddSysCustomKey(key);
  674. return Do(redis => redis.ListLength(key));
  675. }
  676. #endregion 同步方法
  677. #region 异步方法
  678. /// <summary>
  679. /// 移除指定ListId的内部List的值
  680. /// </summary>
  681. /// <param name="key">键</param>
  682. /// <param name="value">值</param>
  683. public Task<long> RemoveListAsync<T>(string key, T value)
  684. {
  685. key = AddSysCustomKey(key);
  686. return Do(db => db.ListRemoveAsync(key, ConvertJson(value)));
  687. }
  688. /// <summary>
  689. /// 获取指定key的List
  690. /// </summary>
  691. /// <typeparam name="T">数据类型</typeparam>
  692. /// <param name="key">键</param>
  693. /// <returns>数据集合</returns>
  694. public async Task<List<T>> ListRangeAsync<T>(string key)
  695. {
  696. if (KeyExists(key))
  697. {
  698. key = AddSysCustomKey(key);
  699. var values = await Do(redis => redis.ListRangeAsync(key));
  700. return ConvetList<T>(values);
  701. }
  702. return new List<T>();
  703. }
  704. /// <summary>
  705. /// 入队
  706. /// </summary>
  707. /// <typeparam name="T">数据类型</typeparam>
  708. /// <param name="key">键</param>
  709. /// <param name="value">值</param>
  710. public async Task<long> ListRightPushAsync<T>(string key, T value)
  711. {
  712. key = AddSysCustomKey(key);
  713. return await Do(db => db.ListRightPushAsync(key, ConvertJson(value)));
  714. }
  715. /// <summary>
  716. /// 出队
  717. /// </summary>
  718. /// <typeparam name="T">数据类型</typeparam>
  719. /// <param name="key">键</param>
  720. /// <returns>对象实例</returns>
  721. public async Task<T> ListRightPopAsync<T>(string key)
  722. {
  723. if (KeyExists(key))
  724. {
  725. key = AddSysCustomKey(key);
  726. var value = await Do(db => db.ListRightPopAsync(key));
  727. return ConvertObj<T>(value);
  728. }
  729. return default(T);
  730. }
  731. /// <summary>
  732. /// 入栈
  733. /// </summary>
  734. /// <typeparam name="T">数据类型</typeparam>
  735. /// <param name="key">键</param>
  736. /// <param name="value">值</param>
  737. public async Task<long> ListLeftPushAsync<T>(string key, T value)
  738. {
  739. key = AddSysCustomKey(key);
  740. return await Do(db => db.ListLeftPushAsync(key, ConvertJson(value)));
  741. }
  742. /// <summary>
  743. /// 出栈
  744. /// </summary>
  745. /// <typeparam name="T">数据类型</typeparam>
  746. /// <param name="key">键</param>
  747. /// <returns>实例对象</returns>
  748. public async Task<T> ListLeftPopAsync<T>(string key)
  749. {
  750. if (KeyExists(key))
  751. {
  752. key = AddSysCustomKey(key);
  753. var value = await Do(db => db.ListLeftPopAsync(key));
  754. return ConvertObj<T>(value);
  755. }
  756. return default(T);
  757. }
  758. /// <summary>
  759. /// 获取集合中的数量
  760. /// </summary>
  761. /// <param name="key">键</param>
  762. /// <returns>数量</returns>
  763. public async Task<long> ListLengthAsync(string key)
  764. {
  765. key = AddSysCustomKey(key);
  766. return await Do(redis => redis.ListLengthAsync(key));
  767. }
  768. #endregion 异步方法
  769. #endregion List
  770. #region SortedSet 有序集合
  771. #region 同步方法
  772. /// <summary>
  773. /// 添加
  774. /// </summary>
  775. /// <param name="key">键</param>
  776. /// <param name="value">值</param>
  777. /// <param name="score">排序号</param>
  778. public bool AddSortedSet<T>(string key, T value, double score)
  779. {
  780. key = AddSysCustomKey(key);
  781. return Do(redis => redis.SortedSetAdd(key, ConvertJson<T>(value), score));
  782. }
  783. /// <summary>
  784. /// 删除
  785. /// </summary>
  786. /// <param name="key">键</param>
  787. /// <param name="value">值</param>
  788. public bool RemoveSortedSet<T>(string key, T value)
  789. {
  790. key = AddSysCustomKey(key);
  791. return Do(redis => redis.SortedSetRemove(key, ConvertJson(value)));
  792. }
  793. /// <summary>
  794. /// 获取全部
  795. /// </summary>
  796. /// <param name="key">键</param>
  797. /// <returns>数据集合</returns>
  798. public List<T> SetRangeSortedByRank<T>(string key)
  799. {
  800. if (KeyExists(key))
  801. {
  802. key = AddSysCustomKey(key);
  803. return Do(redis =>
  804. {
  805. var values = redis.SortedSetRangeByRank(key);
  806. return ConvetList<T>(values);
  807. });
  808. }
  809. return new List<T>();
  810. }
  811. /// <summary>
  812. /// 获取集合中的数量
  813. /// </summary>
  814. /// <param name="key">键</param>
  815. /// <returns>数量</returns>
  816. public long SetSortedLength(string key)
  817. {
  818. key = AddSysCustomKey(key);
  819. return Do(redis => redis.SortedSetLength(key));
  820. }
  821. #endregion 同步方法
  822. #region 异步方法
  823. /// <summary>
  824. /// 添加
  825. /// </summary>
  826. /// <param name="key">键</param>
  827. /// <param name="value">值</param>
  828. /// <param name="score">排序号</param>
  829. public async Task<bool> SortedSetAddAsync<T>(string key, T value, double score)
  830. {
  831. key = AddSysCustomKey(key);
  832. return await Do(redis => redis.SortedSetAddAsync(key, ConvertJson<T>(value), score));
  833. }
  834. /// <summary>
  835. /// 删除
  836. /// </summary>
  837. /// <param name="key">键</param>
  838. /// <param name="value">值</param>
  839. public async Task<bool> SortedSetRemoveAsync<T>(string key, T value)
  840. {
  841. key = AddSysCustomKey(key);
  842. return await Do(redis => redis.SortedSetRemoveAsync(key, ConvertJson(value)));
  843. }
  844. /// <summary>
  845. /// 获取全部
  846. /// </summary>
  847. /// <param name="key">键</param>
  848. /// <returns>数据集合</returns>
  849. public async Task<List<T>> SortedSetRangeByRankAsync<T>(string key)
  850. {
  851. if (KeyExists(key))
  852. {
  853. key = AddSysCustomKey(key);
  854. var values = await Do(redis => redis.SortedSetRangeByRankAsync(key));
  855. return ConvetList<T>(values);
  856. }
  857. return new List<T>();
  858. }
  859. /// <summary>
  860. /// 获取集合中的数量
  861. /// </summary>
  862. /// <param name="key">键</param>
  863. /// <returns>数量</returns>
  864. public async Task<long> SortedSetLengthAsync(string key)
  865. {
  866. key = AddSysCustomKey(key);
  867. return await Do(redis => redis.SortedSetLengthAsync(key));
  868. }
  869. #endregion 异步方法
  870. #endregion SortedSet 有序集合
  871. #region key
  872. /// <summary>
  873. /// 删除单个key
  874. /// </summary>
  875. /// <param name="key">redis key</param>
  876. /// <returns>是否删除成功</returns>
  877. public bool DeleteKey(string key)
  878. {
  879. key = AddSysCustomKey(key);
  880. return Do(db => db.KeyDelete(key));
  881. }
  882. /// <summary>
  883. /// 删除多个key
  884. /// </summary>
  885. /// <param name="keys">rediskey</param>
  886. /// <returns>成功删除的个数</returns>
  887. public long DeleteKey(List<string> keys)
  888. {
  889. List<string> newKeys = keys.Select(AddSysCustomKey).ToList();
  890. return Do(db => db.KeyDelete(ConvertRedisKeys(newKeys)));
  891. }
  892. /// <summary>
  893. /// 判断key是否存储
  894. /// </summary>
  895. /// <param name="key">键</param>
  896. /// <returns>是否存储成功</returns>
  897. public bool KeyExists(string key)
  898. {
  899. key = AddSysCustomKey(key);
  900. return Do(db => db.KeyExists(key));
  901. }
  902. /// <summary>
  903. /// 重新命名key
  904. /// </summary>
  905. /// <param name="key">旧的键</param>
  906. /// <param name="newKey">新的键</param>
  907. /// <returns>处理结果</returns>
  908. public bool RenameKey(string key, string newKey)
  909. {
  910. key = AddSysCustomKey(key);
  911. return Do(db => db.KeyRename(key, newKey));
  912. }
  913. /// <summary>
  914. /// 设置Key的过期时间
  915. /// </summary>
  916. /// <param name="key">键</param>
  917. /// <param name="expiry">过期时间</param>
  918. /// <returns>处理结果</returns>
  919. public bool Expire(string key, TimeSpan? expiry = default(TimeSpan?))
  920. {
  921. key = AddSysCustomKey(key);
  922. return Do(db => db.KeyExpire(key, expiry));
  923. }
  924. #endregion key
  925. #region 发布订阅
  926. /// <summary>
  927. /// Redis发布订阅 订阅
  928. /// </summary>
  929. /// <param name="subChannel">订阅频道</param>
  930. /// <param name="handler">处理过程</param>
  931. public void Subscribe(string subChannel, Action<RedisChannel, RedisValue> handler = null)
  932. {
  933. ISubscriber sub = _conn.GetSubscriber();
  934. sub.Subscribe(subChannel, (channel, message) =>
  935. {
  936. if (handler == null)
  937. {
  938. Console.WriteLine(subChannel + " 订阅收到消息:" + message);
  939. }
  940. else
  941. {
  942. handler(channel, message);
  943. }
  944. });
  945. }
  946. /// <summary>
  947. /// Redis发布订阅 发布
  948. /// </summary>
  949. /// <typeparam name="T">消息对象</typeparam>
  950. /// <param name="channel">发布频道</param>
  951. /// <param name="msg">消息</param>
  952. /// <returns>消息的数量</returns>
  953. public long Publish<T>(string channel, T msg)
  954. {
  955. ISubscriber sub = _conn.GetSubscriber();
  956. return sub.Publish(channel, ConvertJson(msg));
  957. }
  958. /// <summary>
  959. /// Redis发布订阅 取消订阅
  960. /// </summary>
  961. /// <param name="channel">频道</param>
  962. public void Unsubscribe(string channel)
  963. {
  964. ISubscriber sub = _conn.GetSubscriber();
  965. sub.Unsubscribe(channel);
  966. }
  967. /// <summary>
  968. /// Redis发布订阅 取消全部订阅
  969. /// </summary>
  970. public void UnsubscribeAll()
  971. {
  972. ISubscriber sub = _conn.GetSubscriber();
  973. sub.UnsubscribeAll();
  974. }
  975. #endregion 发布订阅
  976. #region 其他
  977. /// <summary>
  978. /// 创建一个事务
  979. /// </summary>
  980. /// <returns>事务对象</returns>
  981. public ITransaction CreateTransaction()
  982. {
  983. return GetDatabase().CreateTransaction();
  984. }
  985. /// <summary>
  986. /// 获得一个数据库实例
  987. /// </summary>
  988. /// <returns>数据库实例</returns>
  989. public IDatabase GetDatabase()
  990. {
  991. return _conn.GetDatabase(DbNum);
  992. }
  993. /// <summary>
  994. /// 获得一个服务器实例
  995. /// </summary>
  996. /// <param name="hostAndPort">服务器地址</param>
  997. /// <returns>服务器实例</returns>
  998. public IServer GetServer(string hostAndPort)
  999. {
  1000. return _conn.GetServer(hostAndPort);
  1001. }
  1002. /// <summary>
  1003. /// 设置前缀
  1004. /// </summary>
  1005. /// <param name="customKey">前缀</param>
  1006. public void SetSysCustomKey(string customKey)
  1007. {
  1008. CustomKey = customKey;
  1009. }
  1010. #endregion 其他
  1011. #region 辅助方法
  1012. private string AddSysCustomKey(string oldKey)
  1013. {
  1014. var prefixKey = CustomKey ?? String.Empty;
  1015. return prefixKey + oldKey;
  1016. }
  1017. private T Do<T>(Func<IDatabase, T> func)
  1018. {
  1019. var database = _conn.GetDatabase(DbNum);
  1020. return func(database);
  1021. }
  1022. private string ConvertJson<T>(T value)
  1023. {
  1024. return JsonConvert.SerializeObject(value);
  1025. }
  1026. private T ConvertObj<T>(RedisValue value)
  1027. {
  1028. return JsonConvert.DeserializeObject<T>(value);
  1029. }
  1030. private List<T> ConvetList<T>(RedisValue[] values)
  1031. {
  1032. List<T> result = new List<T>();
  1033. foreach (var item in values)
  1034. {
  1035. var model = ConvertObj<T>(item);
  1036. result.Add(model);
  1037. }
  1038. return result;
  1039. }
  1040. private RedisKey[] ConvertRedisKeys(List<string> redisKeys)
  1041. {
  1042. return redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray();
  1043. }
  1044. #endregion 辅助方法
  1045. #region 事件
  1046. ///// <summary>
  1047. ///// 配置更改时
  1048. ///// </summary>
  1049. ///// <param name="sender">触发者</param>
  1050. ///// <param name="e">事件参数</param>
  1051. //private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
  1052. //{
  1053. // Console.WriteLine("Configuration changed: " + e.EndPoint);
  1054. //}
  1055. ///// <summary>
  1056. ///// 发生错误时
  1057. ///// </summary>
  1058. ///// <param name="sender"></param>
  1059. ///// <param name="e"></param>
  1060. //private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
  1061. //{
  1062. // Console.WriteLine("ErrorMessage: " + e.Message);
  1063. //}
  1064. ///// <summary>
  1065. ///// 重新建立连接之前的错误
  1066. ///// </summary>
  1067. ///// <param name="sender"></param>
  1068. ///// <param name="e"></param>
  1069. //private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
  1070. //{
  1071. // Console.WriteLine("ConnectionRestored: " + e.EndPoint);
  1072. //}
  1073. ///// <summary>
  1074. ///// 连接失败 , 如果重新连接成功你将不会收到这个通知
  1075. ///// </summary>
  1076. ///// <param name="sender"></param>
  1077. ///// <param name="e"></param>
  1078. //private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
  1079. //{
  1080. // Console.WriteLine("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
  1081. //}
  1082. ///// <summary>
  1083. ///// 更改集群
  1084. ///// </summary>
  1085. ///// <param name="sender"></param>
  1086. ///// <param name="e"></param>
  1087. //private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
  1088. //{
  1089. // Console.WriteLine("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
  1090. //}
  1091. ///// <summary>
  1092. ///// redis类库错误
  1093. ///// </summary>
  1094. ///// <param name="sender"></param>
  1095. ///// <param name="e"></param>
  1096. //private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
  1097. //{
  1098. // Console.WriteLine("InternalError:Message" + e.Exception.Message);
  1099. //}
  1100. #endregion 事件
  1101. /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
  1102. public void Dispose()
  1103. {
  1104. _conn.Dispose();
  1105. }
  1106. }
  1107. }