Redis2MySql.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. "use strict";
  2. var OujRedis = require('./OujRedis.js');
  3. var TableHelper = require('./TableHelper.js');
  4. var r2m_configs = require('../../conf/r2m_config.inc.js');
  5. var php = require('phpjs');
  6. var co = require('co');
  7. /**
  8. * 基本类,提供增删改查
  9. * @param {string} dbKey
  10. * @author benzhan
  11. */
  12. class Redis2MySql {
  13. constructor(tableName, dbKey, cacheKey) {
  14. this.tableName = tableName;
  15. this.dbKey = dbKey || 'default';
  16. this.cacheKey = cacheKey || 'default';
  17. this.cacheInfo = r2m_configs[this.dbKey][tableName];
  18. if (!this.cacheInfo) {
  19. throw new Error("redis没配置table name:" + tableName, CODE_REDIS_ERROR);
  20. }
  21. /**
  22. * @type {TableHelper}
  23. */
  24. this.objTable = new TableHelper(tableName, this.dbKey);
  25. /**
  26. * @type {Redis}
  27. */
  28. this.objRedis = OujRedis.init(this.cacheKey);
  29. }
  30. /**
  31. * 获取行的key
  32. * @param args
  33. * @returns {string}
  34. * @private
  35. */
  36. _getRowKey(args) {
  37. var keys = this.cacheInfo['key'].split(',');
  38. var cacheKeys = [];
  39. keys.map(function(key) {
  40. key = key.trim();
  41. if (args[key]) {
  42. if (Array.isArray(args[key])) {
  43. cacheKeys.push(key + "=" + args[key].join('|'));
  44. } else {
  45. cacheKeys.push(key + "=" + args[key]);
  46. }
  47. }
  48. });
  49. var cacheKey = this.tableName + ":row";
  50. if (cacheKey) {
  51. return cacheKey + ':' + cacheKeys.join(':');
  52. } else {
  53. return cacheKey;
  54. }
  55. }
  56. /**
  57. * 获取getAll的key
  58. * @param args
  59. * @returns {string}
  60. * @private
  61. */
  62. _getAllKey(args) {
  63. var cacheKey = this.tableName + ":all";
  64. var otherCacheKey = cacheKey + ":others";
  65. var key = this.cacheInfo['all_key'];
  66. if (key) {
  67. var keys = key.split(',');
  68. var cacheKeys = [];
  69. keys.map(function(key) {
  70. key = key.trim();
  71. if (Array.isArray(args[key]) || typeof args[key] == 'undefined' || args[key] === null) {
  72. // 如果有数组,或者有key不存在,则归类到others
  73. return otherCacheKey;
  74. } else {
  75. cacheKeys.push(key + "=" + args[key]);
  76. }
  77. });
  78. if (cacheKeys) {
  79. return cacheKey + ':' + cacheKeys.join(':');
  80. } else {
  81. return otherCacheKey;
  82. }
  83. } else {
  84. return otherCacheKey;
  85. }
  86. }
  87. /**
  88. * 获取一个key的数据
  89. * @param where
  90. * @return <NULL, array>
  91. * @public
  92. */
  93. getRow(where) {
  94. var cacheKey = this._getRowKey(where);
  95. var that = this;
  96. return co(function*() {
  97. var data = yield that.objRedis.hgetall(cacheKey);
  98. if (php.empty(data)) {
  99. // 从数据库重建
  100. var row = yield that.objTable.getRow(where);
  101. if (!php.empty(row)) {
  102. // 设置缓存,无需等待成功就能返回
  103. that._setRowCache(row);
  104. }
  105. return row;
  106. } else {
  107. return data;
  108. }
  109. });
  110. }
  111. /**
  112. * 读取多行数据
  113. * @param where
  114. * @param keyWord 查询关键字, array('_field', '_where', '_limit', '_sortKey', '_sortDir', '_lockRow', '_tableName')
  115. * @param updateList 是否强制更新缓存
  116. * @return array:
  117. * @public
  118. */
  119. getAll(where, keyWord, updateList) {
  120. var that = this;
  121. var args = Object.assign(where, keyWord);
  122. var key = php.http_build_query(args);
  123. if (key.length > 32) {
  124. key = php.md5(key);
  125. } else {
  126. key = php.http_build_query(args);
  127. }
  128. return co(function*() {
  129. var cacheKey = that._getAllKey(where) + ":" + key;
  130. var data = null;
  131. if (!updateList) {
  132. data = yield that.objRedis.get(cacheKey);
  133. if (data) {
  134. return JSON.parse(data);
  135. }
  136. }
  137. data = yield that.objTable.getAll(where, keyWord);
  138. // 以下内容只是用来同步redis用的,可以异步跳过
  139. var pipeline = that.objRedis.pipeline();
  140. pipeline.set(cacheKey, JSON.stringify(data));
  141. if (that.cacheInfo['ttl'] > 0) {
  142. pipeline.expire(cacheKey, that.cacheInfo['ttl']);
  143. }
  144. pipeline.exec();
  145. return data;
  146. });
  147. }
  148. /**
  149. * 增加一行数据
  150. * @param args
  151. * @param updateList
  152. * @return int
  153. * @public
  154. */
  155. addObject(args, updateList) {
  156. updateList = updateList === false ? updateList : true;
  157. var that = this;
  158. return co(function*() {
  159. var ret = yield that.objTable.addObject(args);
  160. if (updateList) {
  161. that.delListCache(args);
  162. }
  163. return ret;
  164. });
  165. }
  166. /**
  167. * 删除列表的缓存
  168. * @param where
  169. * @public
  170. */
  171. delListCache(where) {
  172. var that = this;
  173. var cacheKey = that._getAllKey(where);
  174. var otherKey = that.tableName + ":all:others";
  175. return co(function*() {
  176. var keys = [];
  177. if (cacheKey === otherKey) {
  178. // 需要清除所有key删除
  179. cacheKey = that.tableName + ":all";
  180. keys = yield that.objRedis.keys(cacheKey + '*');
  181. } else {
  182. // 除了删除当前keys,还需要删除others
  183. keys = yield that.objRedis.keys(cacheKey + '*');
  184. var keys1 = yield that.objRedis.keys(otherKey + '*');
  185. keys = Object.assign(keys, keys1);
  186. }
  187. if (keys.length > 0) {
  188. that.objRedis.del(keys);
  189. }
  190. return 1;
  191. });
  192. }
  193. /**
  194. * 设置行的缓存
  195. * @param args
  196. * @returns {Array|{index: number, input: string}|*|{arity, flags, keyStart, keyStop, step}}
  197. * @private
  198. */
  199. _setRowCache(args) {
  200. var cacheKey = this._getRowKey(args);
  201. if (!cacheKey) {
  202. var msg = "没设置key:cacheKey,".JSON.stringify(this.cacheInfo);
  203. throw new Error(msg, CODE_REDIS_ERROR);
  204. }
  205. var pipeline = this.objRedis.pipeline();
  206. pipeline.hmset(cacheKey, args);
  207. if (this.cacheInfo['ttl'] > 0) {
  208. pipeline.expire(cacheKey, this.cacheInfo['ttl']);
  209. }
  210. return pipeline.exec();
  211. }
  212. /**
  213. * 更新行缓存
  214. * @param args
  215. * @returns {*}
  216. * @private
  217. */
  218. _updateRowCache(args) {
  219. var cacheKey = this._getRowKey(args);
  220. if (!cacheKey) {
  221. var msg = "没设置key:cacheKey,".JSON.stringify(this.cacheInfo);
  222. throw new Error(msg, CODE_REDIS_ERROR);
  223. }
  224. var that = this;
  225. return co(function *() {
  226. var flag = yield that.objRedis.exists(cacheKey);
  227. if (flag == 1) {
  228. var pipeline = that.objRedis.pipeline();
  229. pipeline.hmset(cacheKey, args);
  230. if (that.cacheInfo['ttl'] > 0) {
  231. pipeline.expire(cacheKey, that.cacheInfo['ttl']);
  232. }
  233. yield pipeline.exec();
  234. return 1;
  235. }
  236. });
  237. }
  238. /**
  239. * 修改一个key的数据
  240. * @param args 更新的内容
  241. * @param where 更新的条件
  242. * @param updateList
  243. * @return int 影响行数
  244. * @public
  245. */
  246. updateObject(args, where, updateList) {
  247. var that = this;
  248. updateList = updateList === false ? updateList : true;
  249. return co(function*() {
  250. var result = yield that.objTable.updateObject(args, where);
  251. args = php.array_merge(args, where);
  252. if (result.affectedRows > 0) {
  253. yield that._updateRowCache(args);
  254. if (updateList) {
  255. that.delListCache(where);
  256. }
  257. }
  258. return result;
  259. });
  260. }
  261. /**
  262. * 设置一个key的数据
  263. * @param args
  264. * @param updateList
  265. * @return int 影响行数
  266. * @public
  267. */
  268. replaceObject(args, updateList) {
  269. var that = this;
  270. return co(function*() {
  271. var result = yield that.objTable.replaceObject(args);
  272. yield that._setRowCache(args);
  273. if (updateList) {
  274. that.delListCache(args);
  275. }
  276. return result;
  277. });
  278. }
  279. /**
  280. * 删除数据
  281. * @param where
  282. * @param updateList
  283. * @throws RedisException
  284. * @return unknown
  285. * @public
  286. */
  287. delObject(where, updateList) {
  288. var that = this;
  289. updateList = updateList === false ? updateList : true;
  290. return co(function*() {
  291. var result = yield that.objTable.delObject(where);
  292. that._delRowCache(where);
  293. if (updateList) {
  294. that.delListCache(where);
  295. }
  296. return result;
  297. });
  298. }
  299. /**
  300. * 删除行的缓存
  301. * @param where
  302. * @throws RedisException
  303. * @private
  304. */
  305. _delRowCache(where) {
  306. var cacheKey = this._getRowKey(where);
  307. if (!cacheKey) {
  308. var msg = "没设置key:cacheKey,".JSON.stringify(this.cacheInfo);
  309. throw new Error(msg, CODE_REDIS_ERROR);
  310. }
  311. return this.objRedis.del(cacheKey);
  312. }
  313. /**
  314. * 关闭连接
  315. * @public
  316. */
  317. close() {
  318. if (this.objTable) {
  319. this.objTable.close();
  320. }
  321. if (this.objRedis) {
  322. this.objRedis.disconnect();
  323. }
  324. }
  325. }
  326. module.exports = Redis2MySql;