如果要在某些在线应用中快速进行计数操作,您可以使用原子计数器实现。使用原子计数器时,您需要将表中的某一列当成一个原子计数器,然后对该列进行原子计数操作。
场景
原子计数器适用于需要快速进行计数操作的场景,例如在某些在线应用中实现统计帖子的PV(实时浏览量)、消息计数等功能。
功能概述
原子计数器可以解决由强一致性导致的写入性能开销的问题。一个RMW(Read-Modify-Write)操作,通过一次网络请求发送到服务器端,服务器端使用内部行锁机制在本地完成RMW的操作。通过原子计数器将分布式计算器的计算逻辑下推到服务器端,在保证强一致性的情况下,提升原子计数器的写入性能。
原子计数操作可能会由于网络超时、系统错误等导致失败。此时只需重试操作即可,但是可能会更新两次原子计数器,导致原子计数器偏多或偏少。针对此类异常场景,建议使用条件更新精确变更列值。
使用原子计数器功能,您可以对某一行中的数据做实时统计。为了实现原子计数器功能,表格存储UpdateRow接口中新增了原子计数器的相关操作,例如对列执行增量变更、返回进行原子计数操作后的列值。
假设您需要使用表格存储来存储图片元信息并统计图片数信息,数据表内每一行对应某一个用户ID,行上的其中一列用于存储上传的图片,另一列用于实时统计上传的图片数。
使用UpdateRow接口增加一张新图片时,原子计数器+1。
使用UpdateRow接口删除一张旧图片时,原子计数器-1。
使用GetRow接口读取原子计数器的值,获取当前用户的图片数。
上述行为具有强一致性,即当增加一张新图片时,原子计数器会相应+1,而不会出现-1的情况。
注意事项
只支持对整型列的列值进行原子计数操作。
作为原子计数器的列,如果写入数据前该列不存在,则默认值为0;如果写入数据前该列已存在且列值非整型,则产生OTSParameterInvalid错误。
增量值可以是正数或负数,但不能出现计算溢出。如果出现计算溢出,则产生OTSParameterInvalid错误。
默认不返回进行原子计数操作的列值,您可以通过相应操作指定返回进行原子计数操作的列值。
在单次更新请求中,不能对某一列同时进行更新和原子计数操作。假设列A已经执行原子计数操作,则列A不能再执行其他操作(例如列的覆盖写,列删除等)。
在一次BatchWriteRow请求中,支持对同一行数据进行多次更新操作。但是如果某一行已进行原子计数操作,则该行在此批量请求中只能出现一次。
原子计数操作只能作用在列值的最新版本,不支持对列值的特定版本做原子计数操作。更新完成后,原子计数操作会插入一个新的数据版本。
使用方式
只支持通过SDK方式使用原子计数器功能。
您可以通过Java SDK、Go SDK、Python SDK、Node.js SDK、.NET SDK和PHP SDK使用原子计数器功能。此处以Java SDK为例介绍原子计数器功能的使用。
写入数据时,使用rowUpdateChange接口对整型列做列值的增量变更,然后读取更新后的新值。
private static void incrementByUpdateRowApi(SyncClient client) {
//构造主键。
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn("<PRIMARY_KEY_NAME>", PrimaryKeyValue.fromString("pk0"));
PrimaryKey primaryKey = primaryKeyBuilder.build();
//设置数据表名称。
RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey);
//将进行原子计数操作的price列的列值+10,不能设置时间戳。
rowUpdateChange.increment(new Column("price", ColumnValue.fromLong(10)));
//设置returnType为ReturnType.RT_AFTER_MODIFY,将进行原子计数操作的列值返回。
rowUpdateChange.addReturnColumn("price");
rowUpdateChange.setReturnType(ReturnType.RT_AFTER_MODIFY);
//对price列进行原子计数操作。
UpdateRowResponse response = client.updateRow(new UpdateRowRequest(rowUpdateChange));
//打印更新后的新值。
Row row = response.getRow();
System.out.println(row);
}
计费说明
使用原子计数器功能不影响现有计费规则。关于计费的更多信息,请参见计费概述。